scran
C++ library for basic single-cell RNA-seq analyses
Loading...
Searching...
No Matches
FitVarianceTrend.hpp
Go to the documentation of this file.
1#ifndef SCRAN_FIT_TREND_VAR_H
2#define SCRAN_FIT_TREND_VAR_H
3
4#include "../utils/macros.hpp"
5
6#include <algorithm>
7#include <vector>
8#include "WeightedLowess/WeightedLowess.hpp"
9
16namespace scran {
17
35public:
39 struct Defaults {
43 static constexpr double minimum_mean = 0.1;
44
48 static constexpr bool filter = true;
49
53 static constexpr bool transform = true;
54
58 static constexpr double span = 0.3;
59
63 static constexpr bool use_fixed_width = false;
64
68 static constexpr double fixed_width = 1;
69
73 static constexpr int minimum_window_count = 200;
74 };
75
76public:
86 span = s;
87 return *this;
88 }
89
98 min_mean = m;
99 return *this;
100 }
101
111 filter = f;
112 return *this;
113 }
114
124 transform = t;
125 return *this;
126 }
127
138 use_fixed_width = u;
139 return *this;
140 }
141
152 fixed_width = f;
153 return *this;
154 }
155
166 minimum_window_count = c;
167 return *this;
168 }
169
170private:
171 double span = Defaults::span;
172 double min_mean = Defaults::minimum_mean;
173 bool filter = Defaults::filter;
174 bool transform = Defaults::transform;
175
176 bool use_fixed_width = Defaults::use_fixed_width;
177 bool fixed_width = Defaults::fixed_width;
178 int minimum_window_count = Defaults::minimum_window_count;
179
180 static double quad(double x) {
181 return x*x*x*x;
182 }
183
184public:
195 void run(size_t n, const double* mean, const double* variance, double* fitted, double* residuals) const {
196 std::vector<double> xbuffer(n), ybuffer(n);
197
198 size_t counter = 0;
199 for (size_t i = 0; i < n; ++i) {
200 if (!filter || mean[i] >= min_mean) {
201 xbuffer[counter] = mean[i];
202 if (transform) {
203 ybuffer[counter] = std::pow(variance[i], 0.25); // Using the same quarter-root transform that limma::voom uses.
204 } else {
205 ybuffer[counter] = variance[i];
206 }
207 ++counter;
208 }
209 }
210
211 if (counter < 2) {
212 throw std::runtime_error("not enough observations above the minimum mean");
213 }
214
215 // Determining the left edge. This needs to be done before
216 // run_in_place, which mutates the input xbuffer.
217 size_t left_index = std::min_element(xbuffer.begin(), xbuffer.begin() + counter) - xbuffer.begin();
218 double left_x = xbuffer[left_index];
219
220 WeightedLowess::WeightedLowess<> smoother;
221 if (use_fixed_width) {
222 smoother.set_span(minimum_window_count);
223 smoother.set_span_as_proportion(false);
224 smoother.set_min_width(fixed_width);
225 } else {
226 smoother.set_span(span);
227 }
228
229 std::vector<double> fbuffer(counter), rbuffer(counter);
230 smoother.run(counter, xbuffer.data(), ybuffer.data(), NULL, fbuffer.data(), rbuffer.data());
231
232 // Identifying the left-most fitted value.
233 double left_fitted = (transform ? quad(fbuffer[left_index]) : fbuffer[left_index]);
234
235 counter = 0;
236 for (size_t i = 0; i < n; ++i) {
237 if (!filter || mean[i] >= min_mean) {
238 fitted[i] = (transform ? quad(fbuffer[counter]) : fbuffer[counter]);
239 ++counter;
240 } else {
241 fitted[i] = mean[i] / left_x * left_fitted; // draw a y = x line to the origin from the left of the fitted trend.
242 }
243 residuals[i] = variance[i] - fitted[i];
244 }
245 return;
246 }
247
248public:
255 struct Results {
259 Results() {}
260
261 Results(size_t n) : fitted(n), residuals(n) {}
269 std::vector<double> fitted;
270
274 std::vector<double> residuals;
275 };
276
286 Results run(size_t n, const double* mean, const double* variance) const {
287 Results output(n);
288 run(n, mean, variance, output.fitted.data(), output.residuals.data());
289 return output;
290 }
291};
292
293}
294
295#endif
Fit a mean-variance trend to log-count data.
Definition FitVarianceTrend.hpp:34
FitVarianceTrend & set_minimum_window_count(int c=Defaults::minimum_window_count)
Definition FitVarianceTrend.hpp:165
Results run(size_t n, const double *mean, const double *variance) const
Definition FitVarianceTrend.hpp:286
void run(size_t n, const double *mean, const double *variance, double *fitted, double *residuals) const
Definition FitVarianceTrend.hpp:195
FitVarianceTrend & set_transform(bool t=Defaults::transform)
Definition FitVarianceTrend.hpp:123
FitVarianceTrend & set_minimum_mean(double m=Defaults::minimum_mean)
Definition FitVarianceTrend.hpp:97
FitVarianceTrend & set_fixed_width(double f=Defaults::fixed_width)
Definition FitVarianceTrend.hpp:151
FitVarianceTrend & set_filter(bool f=Defaults::filter)
Definition FitVarianceTrend.hpp:110
FitVarianceTrend & set_span(double s=Defaults::span)
Definition FitVarianceTrend.hpp:85
FitVarianceTrend & set_use_fixed_width(bool u=Defaults::use_fixed_width)
Definition FitVarianceTrend.hpp:137
Functions for single-cell RNA-seq analyses.
Definition AggregateAcrossCells.hpp:18
Parameter defaults for trend fitting.
Definition FitVarianceTrend.hpp:39
static constexpr int minimum_window_count
Definition FitVarianceTrend.hpp:73
static constexpr double span
Definition FitVarianceTrend.hpp:58
static constexpr bool filter
Definition FitVarianceTrend.hpp:48
static constexpr double minimum_mean
Definition FitVarianceTrend.hpp:43
static constexpr bool use_fixed_width
Definition FitVarianceTrend.hpp:63
static constexpr bool transform
Definition FitVarianceTrend.hpp:53
static constexpr double fixed_width
Definition FitVarianceTrend.hpp:68
Results of the trend fit.
Definition FitVarianceTrend.hpp:255
std::vector< double > fitted
Definition FitVarianceTrend.hpp:269
std::vector< double > residuals
Definition FitVarianceTrend.hpp:274