248 for (
int i = 0; i < differential_analysis::n_summaries; ++i) {
259 for (
int i = 0; i < differential_analysis::n_summaries; ++i) {
342 block_weight_policy = w;
353 variable_block_weight_parameters = v;
383 std::fill(do_cohen.begin(), do_cohen.end(), c);
426 std::fill(do_auc.begin(), do_auc.end(), c);
469 std::fill(do_lfc.begin(), do_lfc.end(), c);
496 do_delta_detected = s;
512 std::fill(do_delta_detected.begin(), do_delta_detected.end(), c);
526 do_delta_detected[s] = c;
535 do_delta_detected[s] = c;
552 set_everyone(differential_analysis::MIN, s);
568 set_everyone(differential_analysis::MEAN, s);
584 set_everyone(differential_analysis::MEDIAN, s);
600 set_everyone(differential_analysis::MAX, s);
616 set_everyone(differential_analysis::MIN_RANK, s);
649 template<
typename Value_,
typename Index_,
typename Group_,
typename Stat_>
650 void run(
const tatami::Matrix<Value_, Index_>* p,
const Group_* group,
651 std::vector<Stat_*> means,
652 std::vector<Stat_*> detected,
653 std::vector<std::vector<Stat_*> > cohen,
654 std::vector<std::vector<Stat_*> > auc,
655 std::vector<std::vector<Stat_*> > lfc,
656 std::vector<std::vector<Stat_*> > delta_detected)
658 differential_analysis::MatrixCalculator runner(nthreads, threshold, block_weight_policy, variable_block_weight_parameters);
660 size_t ngenes = p->nrow();
661 size_t ngroups = means.size();
662 Overlord<Stat_> overlord(ngenes, ngroups, auc.empty());
663 auto state = runner.run(p, group, ngroups, overlord);
665 process_simple_effects(ngenes, ngroups, 1, state, means, detected, cohen, lfc, delta_detected);
666 summarize_auc(ngenes, ngroups, state, auc, overlord.auc_buffer);
701 template<
typename Value_,
typename Index_,
typename Group_,
typename Block_,
typename Stat_>
702 void run_blocked(
const tatami::Matrix<Value_, Index_>* p,
const Group_* group,
const Block_* block,
703 std::vector<Stat_*> means,
704 std::vector<Stat_*> detected,
705 std::vector<std::vector<Stat_*> > cohen,
706 std::vector<std::vector<Stat_*> > auc,
707 std::vector<std::vector<Stat_*> > lfc,
708 std::vector<std::vector<Stat_*> > delta_detected)
719 std::move(delta_detected)
724 differential_analysis::MatrixCalculator runner(nthreads, threshold, block_weight_policy, variable_block_weight_parameters);
726 size_t ngenes = p->nrow();
727 size_t ngroups = means.size();
728 size_t nblocks =
count_ids(p->ncol(), block);
729 Overlord<Stat_> overlord(ngenes, ngroups, auc.empty());
730 auto state = runner.run_blocked(p, group, ngroups, block, nblocks, overlord);
732 int ncombos = ngroups * nblocks;
733 std::vector<std::vector<Stat_> > means_store(ncombos), detected_store(ncombos);
734 std::vector<Stat_*> means2(ncombos), detected2(ncombos);
735 for (
int c = 0; c < ncombos; ++c) {
736 means_store[c].resize(ngenes);
737 detected_store[c].resize(ngenes);
738 means2[c] = means_store[c].data();
739 detected2[c] = detected_store[c].data();
742 process_simple_effects(ngenes, ngroups, nblocks, state, means2, detected2, cohen, lfc, delta_detected);
743 summarize_auc(ngenes, ngroups, state, auc, overlord.auc_buffer);
746 std::vector<double> weights(nblocks);
747 std::vector<Stat_*> mstats(nblocks), dstats(nblocks);
749 for (
int gr = 0; gr < ngroups; ++gr) {
750 for (
int b = 0; b < nblocks; ++b) {
751 size_t offset = gr *
static_cast<size_t>(nblocks) + b;
752 weights[b] = state.level_weight[offset];
753 mstats[b] = means2[offset];
754 dstats[b] = detected2[offset];
763 template<
typename Stat_>
766 Overlord(
size_t nr,
size_t ng,
bool skip_auc) : skipped(skip_auc), auc_buffer(skip_auc ? 0 : nr * ng * ng) {}
768 bool needs_auc()
const {
773 std::vector<Stat_> auc_buffer;
775 Stat_* prepare_auc_buffer(
size_t gene,
size_t ngroups) {
776 return auc_buffer.data() + gene * ngroups * ngroups;
780 template<
typename Stat_>
781 void process_simple_effects(
785 const differential_analysis::MatrixCalculator::State& state,
786 std::vector<Stat_*>& means,
787 std::vector<Stat_*>& detected,
788 std::vector<std::vector<Stat_*> >& cohen,
789 std::vector<std::vector<Stat_*> >& lfc,
790 std::vector<std::vector<Stat_*> >& delta_detected)
792 const auto& level_weight = state.level_weight;
793 auto nlevels = level_weight.size();
794 const auto* tmp_means = state.means.data();
795 const auto* tmp_variances = state.variances.data();
796 const auto* tmp_detected = state.detected.data();
800 auto my_means = tmp_means;
801 auto my_detected = tmp_detected;
802 for (
size_t gene = 0; gene < ngenes; ++gene) {
803 for (
size_t l = 0; l < nlevels; ++l, ++my_means, ++my_detected) {
804 means[l][gene] = *my_means;
805 detected[l][gene] = *my_detected;
813 differential_analysis::EffectsCacher<Stat_> cache(ngenes, ngroups, cache_size);
814 std::vector<double> full_set(ngroups * ngenes);
818 for (
int group = 0; group < ngroups; ++group) {
819 cache.configure(group, full_set);
821 tatami::parallelize([&](
size_t,
size_t start,
size_t length) ->
void {
822 size_t in_offset = nlevels * start;
823 auto my_means = tmp_means + in_offset;
824 auto my_variances = tmp_variances + in_offset;
826 const auto& actions = cache.actions;
827 auto& staging_cache = cache.staging_cache;
829 auto cohen_ptr = full_set.data() + start * ngroups;
830 std::vector<double> effect_buffer(ngroups);
832 for (
size_t gene = start, end = start + length; gene < end; ++gene, my_means += nlevels, my_variances += nlevels, cohen_ptr += ngroups) {
833 for (
int other = 0; other < ngroups; ++other) {
834 if (actions[other] == differential_analysis::CacheAction::SKIP) {
838 if (actions[other] == differential_analysis::CacheAction::COMPUTE) {
839 cohen_ptr[other] = differential_analysis::compute_pairwise_cohens_d<false>(group, other, my_means, my_variances, level_weight, ngroups, nblocks, threshold);
843 auto tmp = differential_analysis::compute_pairwise_cohens_d<true>(group, other, my_means, my_variances, level_weight, ngroups, nblocks, threshold);
844 cohen_ptr[other] = tmp.first;
845 staging_cache[other][gene] = tmp.second;
848 differential_analysis::summarize_comparisons(ngroups, cohen_ptr, group, gene, cohen, effect_buffer);
850 }, ngenes, nthreads);
852 if (cohen[differential_analysis::summary::MIN_RANK].size()) {
853 differential_analysis::compute_min_rank(ngenes, ngroups, group, full_set.data(), cohen[differential_analysis::summary::MIN_RANK][group], nthreads);
856 cache.transfer(group);
862 for (
int group = 0; group < ngroups; ++group) {
863 cache.configure(group, full_set);
865 tatami::parallelize([&](
size_t,
size_t start,
size_t length) ->
void {
866 auto my_means = tmp_means + nlevels * start;
868 const auto& actions = cache.actions;
869 auto& staging_cache = cache.staging_cache;
871 auto lfc_ptr = full_set.data() + start * ngroups;
872 std::vector<double> effect_buffer(ngroups);
874 for (
size_t gene = start, end = start + length; gene < end; ++gene, my_means += nlevels, lfc_ptr += ngroups) {
875 for (
int other = 0; other < ngroups; ++other) {
876 if (actions[other] == differential_analysis::CacheAction::SKIP) {
880 auto val = differential_analysis::compute_pairwise_simple_diff(group, other, my_means, level_weight, ngroups, nblocks);
881 lfc_ptr[other] = val;
882 if (actions[other] == differential_analysis::CacheAction::CACHE) {
883 staging_cache[other][gene] = -val;
887 differential_analysis::summarize_comparisons(ngroups, lfc_ptr, group, gene, lfc, effect_buffer);
889 }, ngenes, nthreads);
891 if (lfc[differential_analysis::summary::MIN_RANK].size()) {
892 differential_analysis::compute_min_rank(ngenes, ngroups, group, full_set.data(), lfc[differential_analysis::summary::MIN_RANK][group], nthreads);
895 cache.transfer(group);
899 if (delta_detected.size()) {
901 for (
int group = 0; group < ngroups; ++group) {
902 cache.configure(group, full_set);
904 tatami::parallelize([&](
size_t,
size_t start,
size_t length) ->
void {
905 auto my_detected = tmp_detected + nlevels * start;
907 const auto& actions = cache.actions;
908 auto& staging_cache = cache.staging_cache;
910 auto delta_detected_ptr = full_set.data() + start * ngroups;
911 std::vector<double> effect_buffer(ngroups);
913 for (
size_t gene = start, end = start + length; gene < end; ++gene, my_detected += nlevels, delta_detected_ptr += ngroups) {
914 for (
int other = 0; other < ngroups; ++other) {
915 if (actions[other] == differential_analysis::CacheAction::SKIP) {
919 auto val = differential_analysis::compute_pairwise_simple_diff(group, other, my_detected, level_weight, ngroups, nblocks);
920 delta_detected_ptr[other] = val;
921 if (actions[other] == differential_analysis::CacheAction::CACHE) {
922 staging_cache[other][gene] = -val;
926 differential_analysis::summarize_comparisons(ngroups, delta_detected_ptr, group, gene, delta_detected, effect_buffer);
928 }, ngenes, nthreads);
930 if (delta_detected[differential_analysis::summary::MIN_RANK].size()) {
931 differential_analysis::compute_min_rank(ngenes, ngroups, group, full_set.data(), delta_detected[differential_analysis::summary::MIN_RANK][group], nthreads);
934 cache.transfer(group);
939 template<
typename Stat_>
943 const differential_analysis::MatrixCalculator::State& state,
944 std::vector<std::vector<Stat_*> >& auc,
945 std::vector<Stat_>& auc_buffer)
949 differential_analysis::summarize_comparisons(ngenes, ngroups, auc_buffer.data(), auc, nthreads);
950 if (auc[differential_analysis::summary::MIN_RANK].size()) {
951 differential_analysis::compute_min_rank(ngenes, ngroups, auc_buffer.data(), auc[differential_analysis::summary::MIN_RANK], nthreads);
965 template<
typename Stat_>
980 auto fill_inner = [&](
int N,
auto& type) {
982 for (
int n = 0; n < N; ++n) {
983 type.emplace_back(ngenes);
987 fill_inner(ngroups,
means);
991 bool has_any =
false;
992 for (
size_t i = 0; i < do_this.size(); ++i) {
1000 effect.resize(differential_analysis::n_summaries);
1001 if (do_this[differential_analysis::MIN]) {
1002 fill_inner(ngroups, effect[differential_analysis::MIN]);
1004 if (do_this[differential_analysis::MEAN]) {
1005 fill_inner(ngroups, effect[differential_analysis::MEAN]);
1007 if (do_this[differential_analysis::MEDIAN]) {
1008 fill_inner(ngroups, effect[differential_analysis::MEDIAN]);
1010 if (do_this[differential_analysis::MAX]) {
1011 fill_inner(ngroups, effect[differential_analysis::MAX]);
1013 if (do_this[differential_analysis::MIN_RANK]) {
1014 fill_inner(ngroups, effect[differential_analysis::MIN_RANK]);
1020 fill_effect(do_cohen,
cohen);
1021 fill_effect(do_auc,
auc);
1022 fill_effect(do_lfc,
lfc);
1036 std::vector<std::vector<std::vector<Stat_> > >
cohen;
1044 std::vector<std::vector<std::vector<Stat_> > >
auc;
1052 std::vector<std::vector<std::vector<Stat_> > >
lfc;
1090 template<
typename Stat_ =
double,
typename Value_,
typename Index_,
typename Group_>
1092 auto ngroups =
count_ids(p->ncol(), group);
1093 Results<Stat_> res(p->nrow(), ngroups, do_cohen, do_auc, do_lfc, do_delta_detected);
1126 template<
typename Stat_ =
double,
typename Value_,
typename Index_,
typename Group_,
typename Block_>
1128 auto ngroups =
count_ids(p->ncol(), group);
1129 Results<Stat_> res(p->nrow(), ngroups, do_cohen, do_auc, do_lfc, do_delta_detected);