120template<
typename Stat_>
195template<
typename Index_,
typename Stat_>
196void process_simple_pairwise_effects(
198 const std::size_t num_groups,
199 const std::size_t num_blocks,
200 const std::size_t num_combos,
201 const std::vector<Stat_>& combo_means,
202 const std::vector<Stat_>& combo_vars,
203 const std::vector<Stat_>& combo_detected,
204 const double threshold,
205 const BlockAverageInfo<Stat_>& average_info,
207 const int num_threads
209 const Stat_* total_weights_ptr = NULL;
210 std::optional<std::vector<Stat_> > total_weights_per_group;
211 if (average_info.use_mean()) {
213 if (num_blocks > 1) {
214 total_weights_per_group = compute_total_weight_per_group(num_groups, num_blocks, average_info.combo_weights().data());
215 total_weights_ptr = total_weights_per_group->data();
217 total_weights_ptr = average_info.combo_weights().data();
222 std::optional<PrecomputedPairwiseWeights<Stat_> > preweights;
223 if (average_info.use_mean()) {
225 preweights.emplace(num_groups, num_blocks, average_info.combo_weights().data());
230 std::optional<std::vector<Stat_> > qbuffer, qrevbuffer;
231 std::optional<quickstats::SingleQuantileVariableNumber<Stat_> > qcalc;
232 if (!average_info.use_mean()) {
234 qrevbuffer.emplace();
235 qcalc.emplace(num_blocks, average_info.quantile());
238 for (Index_ gene = start, end = start + length; gene < end; ++gene) {
239 auto in_offset = sanisizer::product_unsafe<std::size_t>(gene, num_combos);
241 if (!output.
mean.empty()) {
242 const auto tmp_means = combo_means.data() + in_offset;
243 if (average_info.use_mean()) {
244 average_group_stats_blockmean(gene, num_groups, num_blocks, tmp_means, average_info.combo_weights().data(), total_weights_ptr, output.
mean);
246 average_group_stats_blockquantile(gene, num_groups, num_blocks, tmp_means, *qbuffer, *qcalc, output.
mean);
251 const auto tmp_detected = combo_detected.data() + in_offset;
252 if (average_info.use_mean()) {
253 average_group_stats_blockmean(gene, num_groups, num_blocks, tmp_detected, average_info.combo_weights().data(), total_weights_ptr, output.
detected);
255 average_group_stats_blockquantile(gene, num_groups, num_blocks, tmp_detected, *qbuffer, *qcalc, output.
detected);
260 const auto out_offset = sanisizer::product_unsafe<std::size_t>(gene, num_groups, num_groups);
263 const auto tmp_means = combo_means.data() + in_offset;
264 const auto tmp_variances = combo_vars.data() + in_offset;
265 const auto outptr = output.
cohens_d + out_offset;
266 if (average_info.use_mean()) {
267 compute_pairwise_cohens_d_blockmean(tmp_means, tmp_variances, num_groups, num_blocks, threshold, *preweights, outptr);
269 compute_pairwise_cohens_d_blockquantile(tmp_means, tmp_variances, num_groups, num_blocks, threshold, *qbuffer, *qrevbuffer, *qcalc, outptr);
274 const auto tmp_detected = combo_detected.data() + in_offset;
276 if (average_info.use_mean()) {
277 compute_pairwise_simple_diff_blockmean(tmp_detected, num_groups, num_blocks, *preweights, outptr);
279 compute_pairwise_simple_diff_blockquantile(tmp_detected, num_groups, num_blocks, *qbuffer, *qcalc, outptr);
284 const auto tmp_means = combo_means.data() + in_offset;
285 const auto outptr = output.
delta_mean + out_offset;
286 if (average_info.use_mean()) {
287 compute_pairwise_simple_diff_blockmean(tmp_means, num_groups, num_blocks, *preweights, outptr);
289 compute_pairwise_simple_diff_blockquantile(tmp_means, num_groups, num_blocks, *qbuffer, *qcalc, outptr);
293 }, ngenes, num_threads);
304void score_markers_pairwise(
306 const Group_*
const group,
307 const std::size_t num_groups,
308 const Block_*
const block,
309 const std::size_t num_blocks,
310 const std::size_t*
const combo,
311 const std::size_t num_combos,
312 const std::vector<Index_>& combo_sizes,
313 const ScoreMarkersPairwiseOptions& options,
314 const ScoreMarkersPairwiseBuffers<Stat_>& output
316 const auto ngenes = matrix.
nrow();
317 const auto payload_size = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, num_combos);
318 std::vector<Stat_> combo_means, combo_vars, combo_detected;
319 if (!output.mean.empty() || output.cohens_d != NULL || output.delta_mean != NULL) {
320 combo_means.resize(payload_size);
322 if (output.cohens_d != NULL) {
323 combo_vars.resize(payload_size);
325 if (!output.detected.empty() || output.delta_detected != NULL) {
326 combo_detected.resize(payload_size);
331 BlockAverageInfo<Stat_> average_info;
332 if (options.block_average_policy == BlockAveragePolicy::MEAN) {
333 average_info = BlockAverageInfo<Stat_>(
336 options.block_weight_policy,
337 options.variable_block_weight_parameters
341 average_info = BlockAverageInfo<Stat_>(options.block_quantile);
345 scan_matrix_by_row_full_auc<single_block_>(
364 scan_matrix_by_column(
367 if constexpr(single_block_) {
374 if constexpr(single_block_) {
388 process_simple_pairwise_effects(
479template<
typename Value_,
typename Index_,
typename Group_,
typename Stat_>
482 const Group_*
const group,
483 const std::size_t num_groups,
487 const auto group_sizes = tabulate_groups(matrix.
ncol(), group, num_groups);
488 internal::score_markers_pairwise<true>(
492 static_cast<int*
>(NULL),
494 static_cast<std::size_t*
>(NULL),
543template<
typename Value_,
typename Index_,
typename Group_,
typename Block_,
typename Stat_>
546 const Group_*
const group,
547 const std::size_t num_groups,
548 const Block_*
const block,
549 const std::size_t num_blocks,
553 const auto combo_out = create_combinations(matrix.
ncol(), group, num_groups, block, num_blocks);
554 internal::score_markers_pairwise<false>(
560 combo_out.combinations.data(),
561 combo_out.num_combinations,
562 combo_out.frequencies,
572template<
typename Stat_>
580 std::vector<std::vector<Stat_> >
mean;
630template<
typename Index_,
typename Stat_>
633 const std::size_t num_groups,
640 internal::preallocate_average_results(ngenes, num_groups, store.
mean, output.
mean);
643 internal::preallocate_average_results(ngenes, num_groups, store.
detected, output.
detected);
646 const auto num_effect_sizes = sanisizer::product<typename std::vector<Stat_>::size_type>(ngenes, num_groups, num_groups);
649 store.
cohens_d.resize(num_effect_sizes
650#ifdef SCRAN_MARKERS_TEST_INIT
651 , SCRAN_MARKERS_TEST_INIT
657 store.
auc.resize(num_effect_sizes
658#ifdef SCRAN_MARKERS_TEST_INIT
659 , SCRAN_MARKERS_TEST_INIT
662 output.
auc = store.
auc.data();
666#ifdef SCRAN_MARKERS_TEST_INIT
667 , SCRAN_MARKERS_TEST_INIT
674#ifdef SCRAN_MARKERS_TEST_INIT
675 , SCRAN_MARKERS_TEST_INIT
704template<
typename Stat_ =
double,
typename Value_,
typename Index_,
typename Group_>
707 const Group_*
const group,
708 const std::size_t num_groups,
712 auto buffers = preallocate_pairwise_results(matrix.
nrow(), num_groups, res, options);
738template<
typename Stat_ =
double,
typename Value_,
typename Index_,
typename Group_,
typename Block_>
741 const Group_*
const group,
742 const std::size_t num_groups,
743 const Block_*
const block,
744 const std::size_t num_blocks,
748 const auto buffers = preallocate_pairwise_results(matrix.
nrow(), num_groups, res, options);