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 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 compute_pairwise_simple_diff(tmp_detected, ngroups, nblocks, preweights, output.delta_detected + out_offset);
249 }
250
251 if (output.delta_mean != NULL) {
252 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 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
302template<
303 bool single_block_,
304 typename Value_,
305 typename Index_,
306 typename Group_,
307 typename Block_,
308 typename Stat_
309>
311 const tatami::Matrix<Value_, Index_>& matrix,
312 const std::size_t ngroups,
313 const Group_* const group,
314 const std::size_t nblocks,
315 const Block_* const block,
316 const std::size_t ncombos,
317 const std::size_t* const combo,
318 const std::vector<Index_>& combo_sizes,
319 const ScoreMarkersPairwiseOptions& options,
320 const ScoreMarkersPairwiseBuffers<Stat_>& output
321) {
322 const auto ngenes = matrix.nrow();
323 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, ncombos);
324 std::vector<Stat_> combo_means(payload_size), combo_vars(payload_size), combo_detected(payload_size);
325
326 // For a single block, this usually doesn't really matter, but we do it for consistency with the multi-block case,
327 // and to account for variable weighting where non-zero block sizes get zero weight.
328 const auto combo_weights = scran_blocks::compute_weights<Stat_>(
329 combo_sizes,
330 options.block_weight_policy,
331 options.variable_block_weight_parameters
332 );
333
334 if (output.auc != NULL || matrix.prefer_rows()) {
335 scan_matrix_by_row_full_auc<single_block_>(
336 matrix,
337 ngroups,
338 group,
339 nblocks,
340 block,
341 ncombos,
342 combo,
343 combo_means,
344 combo_vars,
345 combo_detected,
346 output.auc,
347 combo_sizes,
348 combo_weights,
349 options.threshold,
350 options.num_threads
351 );
352
353 } else {
354 scan_matrix_by_column(
355 matrix,
356 [&]{
357 if constexpr(single_block_) {
358 return ngroups;
359 } else {
360 return ncombos;
361 }
362 }(),
363 [&]{
364 if constexpr(single_block_) {
365 return group;
366 } else {
367 return combo;
368 }
369 }(),
370 combo_means,
371 combo_vars,
372 combo_detected,
373 combo_sizes,
374 options.num_threads
375 );
376 }
377
378 process_simple_pairwise_effects(
379 matrix.nrow(),
380 ngroups,
381 nblocks,
382 ncombos,
383 combo_means,
384 combo_vars,
385 combo_detected,
386 output,
387 combo_weights,
388 options.threshold,
389 options.num_threads
390 );
391}
392
393}
468template<typename Value_, typename Index_, typename Group_, typename Stat_>
470 const tatami::Matrix<Value_, Index_>& matrix,
471 const Group_* const group,
472 const ScoreMarkersPairwiseOptions& options,
474) {
475 const Index_ NC = matrix.ncol();
476 const auto group_sizes = tatami_stats::tabulate_groups(group, NC);
477 const auto ngroups = sanisizer::cast<std::size_t>(group_sizes.size());
478
479 internal::score_markers_pairwise<true>(
480 matrix,
481 ngroups,
482 group,
483 1,
484 static_cast<int*>(NULL),
485 ngroups,
486 static_cast<std::size_t*>(NULL),
487 group_sizes,
488 options,
489 output
490 );
491}
492
532template<typename Value_, typename Index_, typename Group_, typename Block_, typename Stat_>
534 const tatami::Matrix<Value_, Index_>& matrix,
535 const Group_* const group,
536 const Block_* const block,
537 const ScoreMarkersPairwiseOptions& options,
539) {
540 const Index_ NC = matrix.ncol();
541 const auto ngroups = output.mean.size();
542 const auto nblocks = tatami_stats::total_groups(block, NC);
543
544 const auto combinations = internal::create_combinations(ngroups, group, block, NC);
545 const auto combo_sizes = internal::tabulate_combinations<Index_>(ngroups, nblocks, combinations);
546 const auto ncombos = combo_sizes.size();
547
548 internal::score_markers_pairwise<false>(
549 matrix,
550 sanisizer::cast<std::size_t>(ngroups),
551 group,
552 sanisizer::cast<std::size_t>(nblocks),
553 block,
554 sanisizer::cast<std::size_t>(ncombos),
555 combinations.data(),
556 combo_sizes,
557 options,
558 output
559 );
560}
561
578template<typename Stat_ = double, typename Value_, typename Index_, typename Group_>
580 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
582 auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
583 score_markers_pairwise(matrix, group, options, buffers);
584 return res;
585}
586
606template<typename Stat_ = double, typename Value_, typename Index_, typename Group_, typename Block_>
608 const tatami::Matrix<Value_, Index_>& matrix,
609 const Group_* const group,
610 const Block_* const block,
611 const ScoreMarkersPairwiseOptions& options)
612{
613 const auto ngroups = tatami_stats::total_groups(group, matrix.ncol());
615 const auto buffers = internal::fill_pairwise_results(matrix.nrow(), ngroups, res, options);
616 score_markers_pairwise_blocked(matrix, group, block, options, buffers);
617 return res;
618}
619
620}
621
622#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:469
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:533
void parallelize(Function_ fun, const Index_ tasks, const 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