1#ifndef TOPICKER_TOPICKER_HPP
2#define TOPICKER_TOPICKER_HPP
10#include "sanisizer/sanisizer.hpp"
23template<
typename Stat_>
44template<
typename Input_>
45std::remove_cv_t<std::remove_reference_t<Input_> > I(Input_ x) {
49template<
bool keep_index_,
typename Index_,
typename Stat_,
typename Top_,
class Output_,
class Cmp_,
class CmpEqual_>
50void pick_top_genes(
const Index_ n,
const Stat_* statistic,
const Top_ top, Output_& output,
const Cmp_ cmp,
const CmpEqual_ cmpeq,
const PickTopGenesOptions<Stat_>& options) {
52 if constexpr(keep_index_) {
55 std::fill_n(output, n,
false);
60 if (sanisizer::is_greater_than(top, n)) {
61 if (options.bound.has_value()) {
62 const auto bound = *(options.bound);
63 for (Index_ i = 0; i < n; ++i) {
64 const bool ok = cmp(statistic[i], bound);
65 if constexpr(keep_index_) {
74 if constexpr(keep_index_) {
75 output.resize(sanisizer::cast<
decltype(I(output.size()))>(n));
76 std::iota(output.begin(), output.end(),
static_cast<Index_
>(0));
78 std::fill_n(output, n,
true);
84 auto semi_sorted = sanisizer::create<std::vector<Index_> >(n);
85 std::iota(semi_sorted.begin(), semi_sorted.end(),
static_cast<Index_
>(0));
86 const auto cBegin = semi_sorted.begin(), cMid = cBegin + top - 1, cEnd = semi_sorted.end();
87 std::nth_element(cBegin, cMid, cEnd, [&](Index_ l, Index_ r) ->
bool {
88 auto L = statistic[l], R = statistic[r];
95 const Stat_ threshold = statistic[*cMid];
97 if (options.keep_ties) {
98 if (options.bound.has_value() && !cmp(threshold, *(options.bound))) {
99 const auto bound = *(options.bound);
100 for (Index_ i = 0; i < n; ++i) {
101 const bool ok = cmp(statistic[i], bound);
102 if constexpr(keep_index_) {
111 for (Index_ i = 0; i < n; ++i) {
112 const bool ok = cmpeq(statistic[i], threshold);
113 if constexpr(keep_index_) {
125 if constexpr(keep_index_) {
126 output.reserve(sanisizer::cast<
decltype(I(output.size()))>(top));
128 std::fill_n(output, n,
false);
131 if (options.bound.has_value()) {
132 const auto bound = *(options.bound);
133 Index_ counter = top;
134 while (counter > 0) {
136 auto pos = semi_sorted[counter];
137 if (cmp(statistic[pos], bound)) {
138 if constexpr(keep_index_) {
139 output.push_back(pos);
146 if constexpr(keep_index_) {
147 output.insert(output.end(), semi_sorted.begin(), semi_sorted.begin() + top);
149 for (
decltype(I(top)) i = 0; i < top; ++i) {
150 output[semi_sorted[i]] =
true;
155 if constexpr(keep_index_) {
156 std::sort(output.begin(), output.end());
184template<
typename Stat_,
typename Top_,
typename Bool_>
187 internal::pick_top_genes<false>(
192 [](Stat_ l, Stat_ r) ->
bool {
return l > r; },
193 [](Stat_ l, Stat_ r) ->
bool {
return l >= r; },
197 internal::pick_top_genes<false>(
202 [](Stat_ l, Stat_ r) ->
bool {
return l < r; },
203 [](Stat_ l, Stat_ r) ->
bool {
return l <= r; },
222template<
typename Bool_,
typename Stat_,
typename Top_>
224 auto output = sanisizer::create<std::vector<Bool_> >(n
225#ifdef SCRAN_VARIANCES_TEST_INIT
226 , SCRAN_VARIANCES_TEST_INIT
229 pick_top_genes(n, statistic, top, larger, output.data(), options);
247template<
typename Index_,
typename Stat_,
typename Top_>
249 std::vector<Index_> output;
251 internal::pick_top_genes<true>(
256 [](Stat_ l, Stat_ r) ->
bool {
return l > r; },
257 [](Stat_ l, Stat_ r) ->
bool {
return l >= r; },
261 internal::pick_top_genes<true>(
266 [](Stat_ l, Stat_ r) ->
bool {
return l < r; },
267 [](Stat_ l, Stat_ r) ->
bool {
return l <= r; },
Options for pick_top_genes().
Definition topicks.hpp:24
bool keep_ties
Definition topicks.hpp:36
std::optional< Stat_ > bound
Definition topicks.hpp:30
void pick_top_genes(const std::size_t n, const Stat_ *const statistic, const Top_ top, const bool larger, Bool_ *const output, const PickTopGenesOptions< Stat_ > &options)
Definition topicks.hpp:185
std::vector< Index_ > pick_top_genes_index(const Index_ n, const Stat_ *const statistic, const Top_ top, const bool larger, const PickTopGenesOptions< Stat_ > &options)
Definition topicks.hpp:248