1#ifndef SCRAN_QC_FIND_MEDIAN_MAD_H
2#define SCRAN_QC_FIND_MEDIAN_MAD_H
10#include "tatami_stats/tatami_stats.hpp"
41template<
typename Float_>
78template<
typename Index_,
typename Float_>
80 static_assert(std::is_floating_point<Float_>::value);
84 for (Index_ i = 0; i < num; ++i) {
85 if (std::isnan(metrics[i])) {
86 std::swap(metrics[i], metrics[lost]);
95 for (Index_ i = 0; i < num; ++i, ++copy) {
97 *copy = std::log(*copy);
98 }
else if (*copy == 0) {
99 *copy = -std::numeric_limits<double>::infinity();
101 throw std::runtime_error(
"cannot log-transform negative values");
107 auto median = tatami_stats::medians::direct<Float_>(metrics, num,
false);
112 }
else if (std::isinf(median)) {
126 for (Index_ i = 0; i < num; ++i, ++copy) {
127 *copy = std::abs(*copy - median);
129 auto mad = tatami_stats::medians::direct<Float_>(metrics, num,
false);
152template<
typename Float_ =
double,
typename Index_,
typename Value_>
154 std::unique_ptr<std::vector<Float_> > xbuffer;
155 if (buffer == NULL) {
156 xbuffer = std::make_unique<std::vector<Float_> >(num
157#ifdef SCRAN_QC_TEST_INIT
161 buffer = xbuffer->data();
163 std::copy_n(metrics, num, buffer);
175template<
typename Float_,
typename Index_>
185 template<
typename Block_>
202 template<
typename Block_>
203 void set(Index_ num,
const Block_* block) {
204 my_block_starts.clear();
207 for (Index_ i = 0; i < num; ++i) {
208 size_t candidate = block[i];
209 if (candidate >= my_block_starts.size()) {
210 my_block_starts.resize(candidate + 1);
212 ++my_block_starts[candidate];
216 for (
auto& s : my_block_starts) {
224#ifdef SCRAN_QC_TEST_INIT
228 my_block_ends.resize(my_block_starts.size());
237 std::vector<Float_> my_buffer;
238 std::vector<Index_> my_block_starts;
239 std::vector<Index_> my_block_ends;
268template<
typename Output_ =
double,
typename Index_,
typename Value_,
typename Block_>
271 const Value_* metrics,
276 std::unique_ptr<FindMedianMadWorkspace<Output_, Index_> > xworkspace;
277 if (workspace == NULL) {
278 xworkspace = std::make_unique<FindMedianMadWorkspace<Output_, Index_> >(num, block);
279 workspace = xworkspace.get();
282 std::vector<FindMedianMadResults<Output_> > output;
284 auto& buffer = workspace->my_buffer;
286 std::copy_n(metrics, num, buffer.begin());
291 const auto& starts = workspace->my_block_starts;
292 auto& ends = workspace->my_block_ends;
293 std::copy(starts.begin(), starts.end(), ends.begin());
294 for (Index_ i = 0; i < num; ++i) {
295 auto& pos = ends[block[i]];
296 buffer[pos] = metrics[i];
301 size_t nblocks = starts.size();
302 output.reserve(nblocks);
303 for (
size_t g = 0; g < nblocks; ++g) {
304 output.push_back(
find_median_mad(ends[g] - starts[g], buffer.data() + starts[g], options));
Simple quality control for single-cell data.
Definition adt_quality_control.hpp:20
FindMedianMadResults< Float_ > find_median_mad(Index_ num, Float_ *metrics, const FindMedianMadOptions &options)
Definition find_median_mad.hpp:79
std::vector< FindMedianMadResults< Output_ > > find_median_mad_blocked(Index_ num, const Value_ *metrics, const Block_ *block, FindMedianMadWorkspace< Output_, Index_ > *workspace, const FindMedianMadOptions &options)
Definition find_median_mad.hpp:269