diff --git a/docs/aggregate__across__cells_8hpp.html b/docs/aggregate__across__cells_8hpp.html index c425581..5f442e2 100644 --- a/docs/aggregate__across__cells_8hpp.html +++ b/docs/aggregate__across__cells_8hpp.html @@ -95,18 +95,21 @@
#include <algorithm>
#include <vector>
#include "tatami/tatami.hpp"
+#include "tatami_stats/tatami_stats.hpp"
Include dependency graph for aggregate_across_cells.hpp:
- - - - - - - + + + + + + + + +
diff --git a/docs/aggregate__across__cells_8hpp__incl.map b/docs/aggregate__across__cells_8hpp__incl.map index 7a883f5..3b1ae8d 100644 --- a/docs/aggregate__across__cells_8hpp__incl.map +++ b/docs/aggregate__across__cells_8hpp__incl.map @@ -1,9 +1,11 @@ - - - - - - - + + + + + + + + + diff --git a/docs/aggregate__across__cells_8hpp__incl.md5 b/docs/aggregate__across__cells_8hpp__incl.md5 index 556a471..896357c 100644 --- a/docs/aggregate__across__cells_8hpp__incl.md5 +++ b/docs/aggregate__across__cells_8hpp__incl.md5 @@ -1 +1 @@ -b72cfb3808a6169684e1c0c68fde63d8 \ No newline at end of file +a5850818d6e39fc80cd613493ca5e12c \ No newline at end of file diff --git a/docs/aggregate__across__cells_8hpp__incl.png b/docs/aggregate__across__cells_8hpp__incl.png index 96630e1..8fd1ae3 100644 Binary files a/docs/aggregate__across__cells_8hpp__incl.png and b/docs/aggregate__across__cells_8hpp__incl.png differ diff --git a/docs/aggregate__across__cells_8hpp_source.html b/docs/aggregate__across__cells_8hpp_source.html index 6e748ac..74160e6 100644 --- a/docs/aggregate__across__cells_8hpp_source.html +++ b/docs/aggregate__across__cells_8hpp_source.html @@ -97,295 +97,266 @@
5#include <vector>
6
7#include "tatami/tatami.hpp"
-
8
-
-
14namespace scran_aggregate {
-
15
-
- -
24 bool compute_sums = true;
-
25
-
30 bool compute_detected = true;
-
31
-
36 int num_threads = 1;
-
37};
+
8#include "tatami_stats/tatami_stats.hpp"
+
9
+
+
15namespace scran_aggregate {
+
16
+
+ +
25 bool compute_sums = true;
+
26
+
31 bool compute_detected = true;
+
32
+
37 int num_threads = 1;
+
38};
-
38
-
44template <typename Sum_, typename Detected_>
-
- -
53 std::vector<Sum_*> sums;
-
54
-
62 std::vector<Detected_*> detected;
-
63
-
64};
+
39
+
45template <typename Sum_, typename Detected_>
+
+ +
54 std::vector<Sum_*> sums;
+
55
+
63 std::vector<Detected_*> detected;
+
64
+
65};
-
65
-
71template <typename Sum_, typename Detected_>
-
- -
80 std::vector<std::vector<Sum_> > sums;
-
81
-
89 std::vector<std::vector<Detected_> > detected;
-
90};
+
66
+
72template <typename Sum_, typename Detected_>
+
+ +
81 std::vector<std::vector<Sum_> > sums;
+
82
+
90 std::vector<std::vector<Detected_> > detected;
+
91};
-
91
-
95namespace internal {
-
96
-
97template<bool sparse_, typename Data_, typename Index_, typename Factor_, typename Sum_, typename Detected_>
-
98void compute_aggregate_by_row(
- -
100 const Factor_* factor,
- -
102 const AggregateAcrossCellsOptions& options)
-
103{
-
104 tatami::Options opt;
-
105 opt.sparse_ordered_index = false;
-
106
-
107 tatami::parallelize([&](size_t, Index_ s, Index_ l) {
-
108 auto ext = tatami::consecutive_extractor<sparse_>(&p, true, s, l, opt);
-
109 size_t nsums = buffers.sums.size();
-
110 std::vector<Sum_> tmp_sums(nsums);
-
111 size_t ndetected = buffers.detected.size();
-
112 std::vector<Detected_> tmp_detected(ndetected);
-
113
-
114 auto NC = p.ncol();
-
115 std::vector<Data_> vbuffer(NC);
-
116 typename std::conditional<sparse_, std::vector<Index_>, Index_>::type ibuffer(NC);
-
117
-
118 for (Index_ x = s, end = s + l; x < end; ++x) {
-
119 auto row = [&]() {
-
120 if constexpr(sparse_) {
-
121 return ext->fetch(vbuffer.data(), ibuffer.data());
-
122 } else {
-
123 return ext->fetch(vbuffer.data());
-
124 }
-
125 }();
-
126
-
127 if (nsums) {
-
128 std::fill(tmp_sums.begin(), tmp_sums.end(), 0);
-
129
-
130 if constexpr(sparse_) {
-
131 for (Index_ j = 0; j < row.number; ++j) {
-
132 tmp_sums[factor[row.index[j]]] += row.value[j];
-
133 }
-
134 } else {
-
135 for (Index_ j = 0; j < NC; ++j) {
-
136 tmp_sums[factor[j]] += row[j];
-
137 }
-
138 }
-
139
-
140 // Computing before transferring for more cache-friendliness.
-
141 for (size_t l = 0; l < nsums; ++l) {
-
142 buffers.sums[l][x] = tmp_sums[l];
-
143 }
-
144 }
-
145
-
146 if (ndetected) {
-
147 std::fill(tmp_detected.begin(), tmp_detected.end(), 0);
-
148
-
149 if constexpr(sparse_) {
-
150 for (Index_ j = 0; j < row.number; ++j) {
-
151 tmp_detected[factor[row.index[j]]] += (row.value[j] > 0);
-
152 }
-
153 } else {
-
154 for (Index_ j = 0; j < NC; ++j) {
-
155 tmp_detected[factor[j]] += (row[j] > 0);
-
156 }
-
157 }
-
158
-
159 for (size_t l = 0; l < ndetected; ++l) {
-
160 buffers.detected[l][x] = tmp_detected[l];
-
161 }
-
162 }
-
163 }
-
164 }, p.nrow(), options.num_threads);
-
165}
-
166
-
167template<bool sparse_, typename Data_, typename Index_, typename Factor_, typename Sum_, typename Detected_>
-
168void compute_aggregate_by_column(
- -
170 const Factor_* factor,
-
171 const AggregateAcrossCellsBuffers<Sum_, Detected_>& buffers,
-
172 const AggregateAcrossCellsOptions& options)
-
173{
-
174 tatami::Options opt;
-
175 opt.sparse_ordered_index = false;
-
176
-
177 tatami::parallelize([&](size_t t, Index_ start, Index_ length) {
-
178 auto NC = p.ncol();
-
179 auto ext = tatami::consecutive_extractor<sparse_>(&p, false, static_cast<Index_>(0), NC, start, length, opt);
-
180 std::vector<Data_> vbuffer(length);
-
181 typename std::conditional<sparse_, std::vector<Index_>, Index_>::type ibuffer(length);
-
182
-
183 // Creating local buffers to protect against false sharing in all but
-
184 // the first thread. The first thread has the honor of writing directly
-
185 // to the output buffers, to avoid extra allocations in the serial case
-
186 // where no false sharing can occur.
-
187 std::vector<std::vector<Sum_> > local_sums;
-
188 std::vector<std::vector<Detected_> > local_detected;
-
189 size_t num_sums = buffers.sums.size();
-
190 size_t num_detected = buffers.detected.size();
-
191 if (t != 0) {
-
192 local_sums.reserve(num_sums);
-
193 for (size_t s = 0; s < num_sums; ++s) {
-
194 local_sums.emplace_back(length);
-
195 }
-
196 local_detected.reserve(num_detected);
-
197 for (size_t d = 0; d < num_detected; ++d) {
-
198 local_detected.emplace_back(length);
-
199 }
-
200 } else {
-
201 // Need to zero it in the first thread for consistency with the other threads.
-
202 for (size_t s = 0; s < num_sums; ++s) {
-
203 std::fill_n(buffers.sums[s] + start, length, static_cast<Sum_>(0));
-
204 }
-
205 for (size_t d = 0; d < num_sums; ++d) {
-
206 std::fill_n(buffers.detected[d] + start, length, static_cast<Detected_>(0));
-
207 }
-
208 }
-
209
-
210 for (Index_ x = 0; x < NC; ++x) {
-
211 auto current = factor[x];
-
212
-
213 if constexpr(sparse_) {
-
214 auto col = ext->fetch(vbuffer.data(), ibuffer.data());
-
215 if (num_sums) {
-
216 auto cursum = (t != 0 ? local_sums[current].data() : buffers.sums[current] + start);
-
217 for (Index_ i = 0; i < col.number; ++i) {
-
218 cursum[col.index[i] - start] += col.value[i];
-
219 }
-
220 }
-
221
-
222 if (num_detected) {
-
223 auto curdetected = (t != 0 ? local_detected[current].data() : buffers.detected[current] + start);
-
224 for (Index_ i = 0; i < col.number; ++i) {
-
225 curdetected[col.index[i] - start] += (col.value[i] > 0);
-
226 }
-
227 }
-
228
-
229 } else {
-
230 auto col = ext->fetch(vbuffer.data());
-
231 if (num_sums) {
-
232 auto cursum = (t != 0 ? local_sums[current].data() : buffers.sums[current] + start);
-
233 for (Index_ i = 0; i < length; ++i) {
-
234 cursum[i] += col[i];
-
235 }
-
236 }
-
237
-
238 if (num_detected) {
-
239 auto curdetected = (t != 0 ? local_detected[current].data() : buffers.detected[current] + start);
-
240 for (Index_ i = 0; i < length; ++i) {
-
241 curdetected[i] += (col[i] > 0);
-
242 }
-
243 }
-
244 }
-
245 }
-
246
-
247 if (t != 0) {
-
248 for (size_t s = 0; s < num_sums; ++s) {
-
249 const auto& current = local_sums[s];
-
250 std::copy(current.begin(), current.end(), buffers.sums[s] + start);
-
251 }
-
252 for (size_t d = 0; d < num_detected; ++d) {
-
253 const auto& current = local_detected[d];
-
254 std::copy(current.begin(), current.end(), buffers.detected[d] + start);
-
255 }
-
256 }
-
257 }, p.nrow(), options.num_threads);
-
258}
-
259
-
260}
-
284template<typename Data_, typename Index_, typename Factor_, typename Sum_, typename Detected_>
-
- - -
287 const Factor_* factor,
- -
289 const AggregateAcrossCellsOptions& options)
-
290{
-
291 if (input.prefer_rows()) {
-
292 if (input.sparse()) {
-
293 internal::compute_aggregate_by_row<true>(input, factor, buffers, options);
-
294 } else {
-
295 internal::compute_aggregate_by_row<false>(input, factor, buffers, options);
-
296 }
-
297 } else {
-
298 if (input.sparse()) {
-
299 internal::compute_aggregate_by_column<true>(input, factor, buffers, options);
-
300 } else {
-
301 internal::compute_aggregate_by_column<false>(input, factor, buffers, options);
-
302 }
-
303 }
-
304}
+
92
+
96namespace internal {
+
97
+
98template<bool sparse_, typename Data_, typename Index_, typename Factor_, typename Sum_, typename Detected_>
+
99void compute_aggregate_by_row(
+ +
101 const Factor_* factor,
+ +
103 const AggregateAcrossCellsOptions& options)
+
104{
+
105 tatami::Options opt;
+
106 opt.sparse_ordered_index = false;
+
107
+
108 tatami::parallelize([&](size_t, Index_ s, Index_ l) {
+
109 auto ext = tatami::consecutive_extractor<sparse_>(&p, true, s, l, opt);
+
110 size_t nsums = buffers.sums.size();
+
111 std::vector<Sum_> tmp_sums(nsums);
+
112 size_t ndetected = buffers.detected.size();
+
113 std::vector<Detected_> tmp_detected(ndetected);
+
114
+
115 auto NC = p.ncol();
+
116 std::vector<Data_> vbuffer(NC);
+
117 typename std::conditional<sparse_, std::vector<Index_>, Index_>::type ibuffer(NC);
+
118
+
119 for (Index_ x = s, end = s + l; x < end; ++x) {
+
120 auto row = [&]() {
+
121 if constexpr(sparse_) {
+
122 return ext->fetch(vbuffer.data(), ibuffer.data());
+
123 } else {
+
124 return ext->fetch(vbuffer.data());
+
125 }
+
126 }();
+
127
+
128 if (nsums) {
+
129 std::fill(tmp_sums.begin(), tmp_sums.end(), 0);
+
130
+
131 if constexpr(sparse_) {
+
132 for (Index_ j = 0; j < row.number; ++j) {
+
133 tmp_sums[factor[row.index[j]]] += row.value[j];
+
134 }
+
135 } else {
+
136 for (Index_ j = 0; j < NC; ++j) {
+
137 tmp_sums[factor[j]] += row[j];
+
138 }
+
139 }
+
140
+
141 // Computing before transferring for more cache-friendliness.
+
142 for (size_t l = 0; l < nsums; ++l) {
+
143 buffers.sums[l][x] = tmp_sums[l];
+
144 }
+
145 }
+
146
+
147 if (ndetected) {
+
148 std::fill(tmp_detected.begin(), tmp_detected.end(), 0);
+
149
+
150 if constexpr(sparse_) {
+
151 for (Index_ j = 0; j < row.number; ++j) {
+
152 tmp_detected[factor[row.index[j]]] += (row.value[j] > 0);
+
153 }
+
154 } else {
+
155 for (Index_ j = 0; j < NC; ++j) {
+
156 tmp_detected[factor[j]] += (row[j] > 0);
+
157 }
+
158 }
+
159
+
160 for (size_t l = 0; l < ndetected; ++l) {
+
161 buffers.detected[l][x] = tmp_detected[l];
+
162 }
+
163 }
+
164 }
+
165 }, p.nrow(), options.num_threads);
+
166}
+
167
+
168template<bool sparse_, typename Data_, typename Index_, typename Factor_, typename Sum_, typename Detected_>
+
169void compute_aggregate_by_column(
+ +
171 const Factor_* factor,
+
172 const AggregateAcrossCellsBuffers<Sum_, Detected_>& buffers,
+
173 const AggregateAcrossCellsOptions& options)
+
174{
+
175 tatami::Options opt;
+
176 opt.sparse_ordered_index = false;
+
177
+
178 tatami::parallelize([&](size_t t, Index_ start, Index_ length) {
+
179 auto NC = p.ncol();
+
180 auto ext = tatami::consecutive_extractor<sparse_>(&p, false, static_cast<Index_>(0), NC, start, length, opt);
+
181 std::vector<Data_> vbuffer(length);
+
182 typename std::conditional<sparse_, std::vector<Index_>, Index_>::type ibuffer(length);
+
183
+
184 size_t num_sums = buffers.sums.size();
+
185 auto get_sum = [&](Index_ i) -> Sum_* { return buffers.sums[i]; };
+
186 tatami_stats::LocalOutputBuffers<Sum_, decltype(get_sum)> local_sums(t, num_sums, start, length, std::move(get_sum));
+
187 auto get_detected = [&](Index_ i) -> Detected_* { return buffers.detected[i]; };
+
188 size_t num_detected = buffers.detected.size();
+
189 tatami_stats::LocalOutputBuffers<Detected_, decltype(get_detected)> local_detected(t, num_detected, start, length, std::move(get_detected));
+
190
+
191 for (Index_ x = 0; x < NC; ++x) {
+
192 auto current = factor[x];
+
193
+
194 if constexpr(sparse_) {
+
195 auto col = ext->fetch(vbuffer.data(), ibuffer.data());
+
196 if (num_sums) {
+
197 auto cursum = local_sums.data(current);
+
198 for (Index_ i = 0; i < col.number; ++i) {
+
199 cursum[col.index[i] - start] += col.value[i];
+
200 }
+
201 }
+
202 if (num_detected) {
+
203 auto curdetected = local_detected.data(current);
+
204 for (Index_ i = 0; i < col.number; ++i) {
+
205 curdetected[col.index[i] - start] += (col.value[i] > 0);
+
206 }
+
207 }
+
208
+
209 } else {
+
210 auto col = ext->fetch(vbuffer.data());
+
211 if (num_sums) {
+
212 auto cursum = local_sums.data(current);
+
213 for (Index_ i = 0; i < length; ++i) {
+
214 cursum[i] += col[i];
+
215 }
+
216 }
+
217 if (num_detected) {
+
218 auto curdetected = local_detected.data(current);
+
219 for (Index_ i = 0; i < length; ++i) {
+
220 curdetected[i] += (col[i] > 0);
+
221 }
+
222 }
+
223 }
+
224 }
+
225
+
226 local_sums.transfer();
+
227 local_detected.transfer();
+
228 }, p.nrow(), options.num_threads);
+
229}
+
230
+
231}
+
255template<typename Data_, typename Index_, typename Factor_, typename Sum_, typename Detected_>
+
+ + +
258 const Factor_* factor,
+ +
260 const AggregateAcrossCellsOptions& options)
+
261{
+
262 if (input.prefer_rows()) {
+
263 if (input.sparse()) {
+
264 internal::compute_aggregate_by_row<true>(input, factor, buffers, options);
+
265 } else {
+
266 internal::compute_aggregate_by_row<false>(input, factor, buffers, options);
+
267 }
+
268 } else {
+
269 if (input.sparse()) {
+
270 internal::compute_aggregate_by_column<true>(input, factor, buffers, options);
+
271 } else {
+
272 internal::compute_aggregate_by_column<false>(input, factor, buffers, options);
+
273 }
+
274 }
+
275}
-
305
-
323template<typename Sum_ = double, typename Detected_ = int, typename Data_, typename Index_, typename Factor_>
-
- - -
326 const Factor_* factor,
-
327 const AggregateAcrossCellsOptions& options)
-
328{
-
329 size_t NC = input.ncol();
-
330 size_t nlevels = (NC ? *std::max_element(factor, factor + NC) + 1 : 0);
-
331 size_t ngenes = input.nrow();
-
332
- - -
335
-
336 if (options.compute_sums) {
-
337 output.sums.resize(nlevels, std::vector<Sum_>(ngenes
-
338#ifdef SCRAN_AGGREGATE_TEST_INIT
-
339 , SCRAN_AGGREGATE_TEST_INIT
-
340#endif
-
341 ));
-
342 buffers.sums.resize(nlevels);
-
343 for (size_t l = 0; l < nlevels; ++l) {
-
344 buffers.sums[l] = output.sums[l].data();
-
345 }
-
346 }
-
347
-
348 if (options.compute_detected) {
-
349 output.detected.resize(nlevels, std::vector<Detected_>(ngenes
-
350#ifdef SCRAN_AGGREGATE_TEST_INIT
-
351 , SCRAN_AGGREGATE_TEST_INIT
-
352#endif
-
353 ));
-
354 buffers.detected.resize(nlevels);
-
355 for (size_t l = 0; l < nlevels; ++l) {
-
356 buffers.detected[l] = output.detected[l].data();
-
357 }
-
358 }
-
359
-
360 aggregate_across_cells(input, factor, buffers, options);
-
361 return output;
-
362}
+
276
+
294template<typename Sum_ = double, typename Detected_ = int, typename Data_, typename Index_, typename Factor_>
+
+ + +
297 const Factor_* factor,
+
298 const AggregateAcrossCellsOptions& options)
+
299{
+
300 size_t NC = input.ncol();
+
301 size_t nlevels = (NC ? *std::max_element(factor, factor + NC) + 1 : 0);
+
302 size_t ngenes = input.nrow();
+
303
+ + +
306
+
307 if (options.compute_sums) {
+
308 output.sums.resize(nlevels, std::vector<Sum_>(ngenes
+
309#ifdef SCRAN_AGGREGATE_TEST_INIT
+
310 , SCRAN_AGGREGATE_TEST_INIT
+
311#endif
+
312 ));
+
313 buffers.sums.resize(nlevels);
+
314 for (size_t l = 0; l < nlevels; ++l) {
+
315 buffers.sums[l] = output.sums[l].data();
+
316 }
+
317 }
+
318
+
319 if (options.compute_detected) {
+
320 output.detected.resize(nlevels, std::vector<Detected_>(ngenes
+
321#ifdef SCRAN_AGGREGATE_TEST_INIT
+
322 , SCRAN_AGGREGATE_TEST_INIT
+
323#endif
+
324 ));
+
325 buffers.detected.resize(nlevels);
+
326 for (size_t l = 0; l < nlevels; ++l) {
+
327 buffers.detected[l] = output.detected[l].data();
+
328 }
+
329 }
+
330
+
331 aggregate_across_cells(input, factor, buffers, options);
+
332 return output;
+
333}
-
363
-
364}
+
334
+
335}
-
365
-
366#endif
+
336
+
337#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
virtual std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const=0
-
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:14
-
void aggregate_across_cells(const tatami::Matrix< Data_, Index_ > &input, const Factor_ *factor, const AggregateAcrossCellsBuffers< Sum_, Detected_ > &buffers, const AggregateAcrossCellsOptions &options)
Definition aggregate_across_cells.hpp:285
+
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:15
+
void aggregate_across_cells(const tatami::Matrix< Data_, Index_ > &input, const Factor_ *factor, const AggregateAcrossCellsBuffers< Sum_, Detected_ > &buffers, const AggregateAcrossCellsOptions &options)
Definition aggregate_across_cells.hpp:256
void parallelize(Function_ fun, Index_ tasks, int threads)
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
-
Buffers for aggregate_across_cells().
Definition aggregate_across_cells.hpp:45
-
std::vector< Detected_ * > detected
Definition aggregate_across_cells.hpp:62
-
std::vector< Sum_ * > sums
Definition aggregate_across_cells.hpp:53
-
Options for aggregate_across_cells().
Definition aggregate_across_cells.hpp:19
-
int num_threads
Definition aggregate_across_cells.hpp:36
-
bool compute_detected
Definition aggregate_across_cells.hpp:30
-
bool compute_sums
Definition aggregate_across_cells.hpp:24
-
Results of aggregate_across_cells().
Definition aggregate_across_cells.hpp:72
-
std::vector< std::vector< Detected_ > > detected
Definition aggregate_across_cells.hpp:89
-
std::vector< std::vector< Sum_ > > sums
Definition aggregate_across_cells.hpp:80
+
Buffers for aggregate_across_cells().
Definition aggregate_across_cells.hpp:46
+
std::vector< Detected_ * > detected
Definition aggregate_across_cells.hpp:63
+
std::vector< Sum_ * > sums
Definition aggregate_across_cells.hpp:54
+
Options for aggregate_across_cells().
Definition aggregate_across_cells.hpp:20
+
int num_threads
Definition aggregate_across_cells.hpp:37
+
bool compute_detected
Definition aggregate_across_cells.hpp:31
+
bool compute_sums
Definition aggregate_across_cells.hpp:25
+
Results of aggregate_across_cells().
Definition aggregate_across_cells.hpp:73
+
std::vector< std::vector< Detected_ > > detected
Definition aggregate_across_cells.hpp:90
+
std::vector< std::vector< Sum_ > > sums
Definition aggregate_across_cells.hpp:81
bool sparse_ordered_index
diff --git a/docs/aggregate__across__genes_8hpp.html b/docs/aggregate__across__genes_8hpp.html index 857dfeb..93c879e 100644 --- a/docs/aggregate__across__genes_8hpp.html +++ b/docs/aggregate__across__genes_8hpp.html @@ -97,22 +97,25 @@ #include <unordered_set>
#include <stdexcept>
#include "tatami/tatami.hpp"
+#include "tatami_stats/tatami_stats.hpp"
Include dependency graph for aggregate_across_genes.hpp:
- - - - - - - - - - - + + + + + + + + + + + + +
diff --git a/docs/aggregate__across__genes_8hpp__incl.map b/docs/aggregate__across__genes_8hpp__incl.map index a652c8c..23bc26f 100644 --- a/docs/aggregate__across__genes_8hpp__incl.map +++ b/docs/aggregate__across__genes_8hpp__incl.map @@ -1,13 +1,15 @@ - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/docs/aggregate__across__genes_8hpp__incl.md5 b/docs/aggregate__across__genes_8hpp__incl.md5 index ec7799b..54f2f86 100644 --- a/docs/aggregate__across__genes_8hpp__incl.md5 +++ b/docs/aggregate__across__genes_8hpp__incl.md5 @@ -1 +1 @@ -6fa151930ef3853992bf2df66624d6b1 \ No newline at end of file +f55e61a274620c8ce209809a4a6ab120 \ No newline at end of file diff --git a/docs/aggregate__across__genes_8hpp__incl.png b/docs/aggregate__across__genes_8hpp__incl.png index 153f361..d58d681 100644 Binary files a/docs/aggregate__across__genes_8hpp__incl.png and b/docs/aggregate__across__genes_8hpp__incl.png differ diff --git a/docs/aggregate__across__genes_8hpp_source.html b/docs/aggregate__across__genes_8hpp_source.html index 1949123..2e1a939 100644 --- a/docs/aggregate__across__genes_8hpp_source.html +++ b/docs/aggregate__across__genes_8hpp_source.html @@ -99,313 +99,297 @@
7#include <stdexcept>
8
9#include "tatami/tatami.hpp"
-
10
-
16namespace scran_aggregate {
-
17
-
- -
26 int num_threads = 1;
-
27
-
32 bool average = false;
-
33};
+
10#include "tatami_stats/tatami_stats.hpp"
+
11
+
17namespace scran_aggregate {
+
18
+
+ +
27 int num_threads = 1;
+
28
+
33 bool average = false;
+
34};
-
34
-
39template <typename Sum_>
-
- -
46 std::vector<Sum_*> sum;
-
47};
+
35
+
40template <typename Sum_>
+
+ +
47 std::vector<Sum_*> sum;
+
48};
-
48
-
53template <typename Sum_>
-
- -
60 std::vector<std::vector<Sum_> > sum;
-
61};
+
49
+
54template <typename Sum_>
+
+ +
61 std::vector<std::vector<Sum_> > sum;
+
62};
-
62
-
66namespace aggregate_across_genes_internal {
-
67
-
68template<typename Index_, typename Gene_, typename Weight_>
-
69std::vector<Gene_> create_subset(const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets, Index_ nrow) {
-
70 std::unordered_set<Gene_> of_interest;
-
71 for (const auto& set : gene_sets) {
-
72 auto set_size = std::get<0>(set);
-
73 auto set_genes = std::get<1>(set);
-
74 of_interest.insert(set_genes, set_genes + set_size);
-
75 }
-
76
-
77 std::vector<Index_> subset(of_interest.begin(), of_interest.end());
-
78 if (!subset.empty()) {
-
79 std::sort(subset.begin(), subset.end());
-
80 if (subset.front() < 0 || subset.back() >= nrow) {
-
81 throw std::runtime_error("set indices are out of range");
-
82 }
-
83 }
-
84
-
85 return subset;
-
86}
-
87
-
88template<typename Index_>
-
89std::pair<std::vector<Index_>, Index_> create_subset_mapping(const std::vector<Index_>& subset) {
-
90 Index_ offset = 0;
-
91 size_t span = subset.back() - offset + 1;
-
92 std::vector<Index_> mapping(span);
-
93 size_t nsubs = subset.size();
-
94 for (size_t i = 0; i < nsubs; ++i) {
-
95 mapping[subset[i] - offset] = i;
-
96 }
-
97 return std::make_pair(std::move(mapping), offset);
-
98}
-
99
-
100template<typename Data_, typename Index_, typename Gene_, typename Weight_, typename Sum_>
-
101void compute_aggregate_by_column(
- -
103 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
-
104 const AggregateAcrossGenesBuffers<Sum_>& buffers,
-
105 const AggregateAcrossGenesOptions& options)
-
106{
-
107 // Identifying the subset of rows that actually need to be extracted.
-
108 tatami::VectorPtr<Index_> subset_of_interest = std::make_shared<std::vector<Index_> >(create_subset<Index_>(gene_sets, p.nrow()));
-
109 const auto& subset = *subset_of_interest;
-
110 size_t nsubs = subset.size();
-
111
-
112 // Creating a mapping back to the gene indices in the subset.
-
113 const size_t num_sets = gene_sets.size();
-
114 std::vector<std::pair<std::vector<Index_>, const Weight_*> > remapping(num_sets);
-
115 if (nsubs) {
-
116 auto sub_mapping = create_subset_mapping(subset);
-
117 const auto& mapping = sub_mapping.first;
-
118 Gene_ offset = sub_mapping.second;
-
119
-
120 for (size_t s = 0; s < num_sets; ++s) {
-
121 const auto& set = gene_sets[s];
-
122 auto set_size = std::get<0>(set);
-
123 auto set_genes = std::get<1>(set);
-
124
-
125 auto& remapped = remapping[s].first;
-
126 remapped.reserve(set_size);
-
127 for (size_t g = 0; g < set_size; ++g) {
-
128 remapped.push_back(mapping[set_genes[g] - offset]);
-
129 }
-
130 remapping[s].second = std::get<2>(set);
-
131 }
-
132 }
-
133
-
134 tatami::parallelize([&](size_t, Index_ start, Index_ length) {
-
135 // We extract as sparse even if it is dense, as it's just
-
136 // easier to index from a dense vector.
-
137 auto ext = tatami::consecutive_extractor<false>(&p, false, start, length, subset_of_interest);
-
138 std::vector<Data_> vbuffer(nsubs);
-
139
-
140 for (Index_ x = start, end = start + length; x < end; ++x) {
-
141 auto ptr = ext->fetch(vbuffer.data());
-
142 for (size_t s = 0; s < num_sets; ++s) {
-
143 const auto& set = remapping[s];
-
144
-
145 Sum_ value = 0;
-
146 if (set.second) {
-
147 for (size_t i = 0, send = set.first.size(); i < send; ++i) {
-
148 value += ptr[set.first[i]] * set.second[i];
-
149 }
-
150 } else {
-
151 for (auto ix : set.first) {
-
152 value += ptr[ix];
-
153 }
-
154 }
-
155
-
156 buffers.sum[s][x] = value;
-
157 }
-
158 }
-
159
-
160 }, p.ncol(), options.num_threads);
-
161}
-
162
-
163template<typename Data_, typename Index_, typename Gene_, typename Weight_, typename Sum_>
-
164void compute_aggregate_by_row(
- -
166 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
-
167 const AggregateAcrossGenesBuffers<Sum_>& buffers,
-
168 const AggregateAcrossGenesOptions& options)
-
169{
-
170 // Identifying the subset of rows that actually need to be extracted.
-
171 auto subset = create_subset<Index_>(gene_sets, p.nrow());
-
172 size_t nsubs = subset.size();
-
173 auto sub_oracle = std::make_shared<tatami::FixedViewOracle<Index_> >(subset.data(), nsubs);
-
174
-
175 const size_t num_sets = gene_sets.size();
-
176 std::vector<std::vector<std::pair<size_t, Weight_> > > remapping(nsubs);
-
177 if (nsubs) {
-
178 auto sub_mapping = create_subset_mapping(subset);
-
179 const auto& mapping = sub_mapping.first;
-
180 Gene_ offset = sub_mapping.second;
-
181
-
182 for (size_t s = 0; s < num_sets; ++s) {
-
183 const auto& set = gene_sets[s];
-
184 auto set_size = std::get<0>(set);
-
185 auto set_genes = std::get<1>(set);
-
186 auto set_weights = std::get<2>(set);
-
187
-
188 if (set_weights) {
-
189 for (size_t g = 0; g < set_size; ++g) {
-
190 remapping[mapping[set_genes[g] - offset]].emplace_back(s, set_weights[g]);
-
191 }
-
192 } else {
-
193 for (size_t g = 0; g < set_size; ++g) {
-
194 remapping[mapping[set_genes[g] - offset]].emplace_back(s, 1);
-
195 }
-
196 }
-
197 }
-
198 }
-
199
-
200 tatami::parallelize([&](size_t t, Index_ start, Index_ length) {
-
201 std::vector<std::vector<Data_> > local_buffers;
-
202 if (t != 0) {
-
203 // Creating local buffers to protect against false sharing in t > 0.
-
204 local_buffers.reserve(num_sets);
-
205 for (size_t s = 0; s < num_sets; ++s) {
-
206 local_buffers.emplace_back(length);
-
207 }
-
208 } else {
-
209 // We still use the output buffers to write when t == 0, to avoid
-
210 // penalizing the serial case where no false sharing can occur. This
-
211 // requires zeroing for consistency with the local_buffers.
-
212 for (size_t s = 0; s < num_sets; ++s) {
-
213 std::fill_n(buffers.sum[s] + start, length, static_cast<Sum_>(0));
-
214 }
-
215 }
-
216
-
217 if (p.sparse()) {
-
218 auto ext = tatami::new_extractor<true, true>(&p, true, sub_oracle, start, length);
-
219 std::vector<Data_> vbuffer(length);
-
220 std::vector<Index_> ibuffer(length);
+
63
+
67namespace aggregate_across_genes_internal {
+
68
+
69template<typename Index_, typename Gene_, typename Weight_>
+
70std::vector<Gene_> create_subset(const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets, Index_ nrow) {
+
71 std::unordered_set<Gene_> of_interest;
+
72 for (const auto& set : gene_sets) {
+
73 auto set_size = std::get<0>(set);
+
74 auto set_genes = std::get<1>(set);
+
75 of_interest.insert(set_genes, set_genes + set_size);
+
76 }
+
77
+
78 std::vector<Index_> subset(of_interest.begin(), of_interest.end());
+
79 if (!subset.empty()) {
+
80 std::sort(subset.begin(), subset.end());
+
81 if (subset.front() < 0 || subset.back() >= nrow) {
+
82 throw std::runtime_error("set indices are out of range");
+
83 }
+
84 }
+
85
+
86 return subset;
+
87}
+
88
+
89template<typename Index_>
+
90std::pair<std::vector<Index_>, Index_> create_subset_mapping(const std::vector<Index_>& subset) {
+
91 Index_ offset = 0;
+
92 size_t span = subset.back() - offset + 1;
+
93 std::vector<Index_> mapping(span);
+
94 size_t nsubs = subset.size();
+
95 for (size_t i = 0; i < nsubs; ++i) {
+
96 mapping[subset[i] - offset] = i;
+
97 }
+
98 return std::make_pair(std::move(mapping), offset);
+
99}
+
100
+
101template<typename Data_, typename Index_, typename Gene_, typename Weight_, typename Sum_>
+
102void compute_aggregate_by_column(
+ +
104 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
+
105 const AggregateAcrossGenesBuffers<Sum_>& buffers,
+
106 const AggregateAcrossGenesOptions& options)
+
107{
+
108 // Identifying the subset of rows that actually need to be extracted.
+
109 tatami::VectorPtr<Index_> subset_of_interest = std::make_shared<std::vector<Index_> >(create_subset<Index_>(gene_sets, p.nrow()));
+
110 const auto& subset = *subset_of_interest;
+
111 size_t nsubs = subset.size();
+
112
+
113 // Creating a mapping back to the gene indices in the subset.
+
114 const size_t num_sets = gene_sets.size();
+
115 std::vector<std::pair<std::vector<Index_>, const Weight_*> > remapping(num_sets);
+
116 if (nsubs) {
+
117 auto sub_mapping = create_subset_mapping(subset);
+
118 const auto& mapping = sub_mapping.first;
+
119 Gene_ offset = sub_mapping.second;
+
120
+
121 for (size_t s = 0; s < num_sets; ++s) {
+
122 const auto& set = gene_sets[s];
+
123 auto set_size = std::get<0>(set);
+
124 auto set_genes = std::get<1>(set);
+
125
+
126 auto& remapped = remapping[s].first;
+
127 remapped.reserve(set_size);
+
128 for (size_t g = 0; g < set_size; ++g) {
+
129 remapped.push_back(mapping[set_genes[g] - offset]);
+
130 }
+
131 remapping[s].second = std::get<2>(set);
+
132 }
+
133 }
+
134
+
135 tatami::parallelize([&](size_t, Index_ start, Index_ length) {
+
136 // We extract as sparse even if it is dense, as it's just
+
137 // easier to index from a dense vector.
+
138 auto ext = tatami::consecutive_extractor<false>(&p, false, start, length, subset_of_interest);
+
139 std::vector<Data_> vbuffer(nsubs);
+
140
+
141 for (Index_ x = start, end = start + length; x < end; ++x) {
+
142 auto ptr = ext->fetch(vbuffer.data());
+
143 for (size_t s = 0; s < num_sets; ++s) {
+
144 const auto& set = remapping[s];
+
145
+
146 Sum_ value = 0;
+
147 if (set.second) {
+
148 for (size_t i = 0, send = set.first.size(); i < send; ++i) {
+
149 value += ptr[set.first[i]] * set.second[i];
+
150 }
+
151 } else {
+
152 for (auto ix : set.first) {
+
153 value += ptr[ix];
+
154 }
+
155 }
+
156
+
157 buffers.sum[s][x] = value;
+
158 }
+
159 }
+
160
+
161 }, p.ncol(), options.num_threads);
+
162}
+
163
+
164template<typename Data_, typename Index_, typename Gene_, typename Weight_, typename Sum_>
+
165void compute_aggregate_by_row(
+ +
167 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
+
168 const AggregateAcrossGenesBuffers<Sum_>& buffers,
+
169 const AggregateAcrossGenesOptions& options)
+
170{
+
171 // Identifying the subset of rows that actually need to be extracted.
+
172 auto subset = create_subset<Index_>(gene_sets, p.nrow());
+
173 size_t nsubs = subset.size();
+
174 auto sub_oracle = std::make_shared<tatami::FixedViewOracle<Index_> >(subset.data(), nsubs);
+
175
+
176 const size_t num_sets = gene_sets.size();
+
177 std::vector<std::vector<std::pair<size_t, Weight_> > > remapping(nsubs);
+
178 if (nsubs) {
+
179 auto sub_mapping = create_subset_mapping(subset);
+
180 const auto& mapping = sub_mapping.first;
+
181 Gene_ offset = sub_mapping.second;
+
182
+
183 for (size_t s = 0; s < num_sets; ++s) {
+
184 const auto& set = gene_sets[s];
+
185 auto set_size = std::get<0>(set);
+
186 auto set_genes = std::get<1>(set);
+
187 auto set_weights = std::get<2>(set);
+
188
+
189 if (set_weights) {
+
190 for (size_t g = 0; g < set_size; ++g) {
+
191 remapping[mapping[set_genes[g] - offset]].emplace_back(s, set_weights[g]);
+
192 }
+
193 } else {
+
194 for (size_t g = 0; g < set_size; ++g) {
+
195 remapping[mapping[set_genes[g] - offset]].emplace_back(s, 1);
+
196 }
+
197 }
+
198 }
+
199 }
+
200
+
201 tatami::parallelize([&](size_t t, Index_ start, Index_ length) {
+
202 auto get_sum = [&](Index_ i) -> Sum_* { return buffers.sum[i]; };
+
203 tatami_stats::LocalOutputBuffers<Sum_, decltype(get_sum)> local_sums(t, num_sets, start, length, std::move(get_sum));
+
204
+
205 if (p.sparse()) {
+
206 auto ext = tatami::new_extractor<true, true>(&p, true, sub_oracle, start, length);
+
207 std::vector<Data_> vbuffer(length);
+
208 std::vector<Index_> ibuffer(length);
+
209
+
210 for (size_t sub = 0; sub < nsubs; ++sub) {
+
211 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
+
212
+
213 for (const auto& sw : remapping[sub]) {
+
214 auto outptr = local_sums.data(sw.first);
+
215 auto wt = sw.second;
+
216 for (Index_ c = 0; c < range.number; ++c) {
+
217 outptr[range.index[c] - start] += range.value[c] * wt;
+
218 }
+
219 }
+
220 }
221
-
222 for (size_t sub = 0; sub < nsubs; ++sub) {
-
223 auto range = ext->fetch(vbuffer.data(), ibuffer.data());
-
224 for (const auto& sw : remapping[sub]) {
-
225 auto wt = sw.second;
-
226 auto outptr = (t != 0 ? local_buffers[sw.first].data() : buffers.sum[sw.first] + start);
-
227 for (Index_ c = 0; c < range.number; ++c) {
-
228 outptr[range.index[c] - start] += range.value[c] * wt;
-
229 }
-
230 }
-
231 }
-
232
-
233 } else {
-
234 auto ext = tatami::new_extractor<false, true>(&p, true, sub_oracle, start, length);
-
235 std::vector<Data_> vbuffer(length);
-
236
-
237 for (size_t sub = 0; sub < nsubs; ++sub) {
-
238 auto ptr = ext->fetch(vbuffer.data());
-
239 for (const auto& sw : remapping[sub]) {
-
240 auto outptr = (t != 0 ? local_buffers[sw.first].data() : buffers.sum[sw.first] + start);
-
241 auto wt = sw.second;
-
242 for (Index_ cell = 0; cell < length; ++cell) {
-
243 outptr[cell] += ptr[cell] * wt;
-
244 }
-
245 }
-
246 }
-
247 }
-
248
-
249 if (t != 0) {
-
250 for (size_t s = 0; s < num_sets; ++s) {
-
251 const auto& current = local_buffers[s];
-
252 std::copy(current.begin(), current.end(), buffers.sum[s] + start);
-
253 }
-
254 }
-
255 }, p.ncol(), options.num_threads);
-
256}
-
257
-
258}
-
283template<typename Data_, typename Index_, typename Gene_, typename Weight_, typename Sum_>
-
- - -
286 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
- -
288 const AggregateAcrossGenesOptions& options)
-
289{
-
290 if (input.prefer_rows()) {
-
291 aggregate_across_genes_internal::compute_aggregate_by_row(input, gene_sets, buffers, options);
-
292 } else {
-
293 aggregate_across_genes_internal::compute_aggregate_by_column(input, gene_sets, buffers, options);
-
294 }
+
222 } else {
+
223 auto ext = tatami::new_extractor<false, true>(&p, true, sub_oracle, start, length);
+
224 std::vector<Data_> vbuffer(length);
+
225
+
226 for (size_t sub = 0; sub < nsubs; ++sub) {
+
227 auto ptr = ext->fetch(vbuffer.data());
+
228 for (const auto& sw : remapping[sub]) {
+
229 auto outptr = local_sums.data(sw.first);
+
230 auto wt = sw.second;
+
231 for (Index_ cell = 0; cell < length; ++cell) {
+
232 outptr[cell] += ptr[cell] * wt;
+
233 }
+
234 }
+
235 }
+
236 }
+
237
+
238 local_sums.transfer();
+
239 }, p.ncol(), options.num_threads);
+
240}
+
241
+
242}
+
267template<typename Data_, typename Index_, typename Gene_, typename Weight_, typename Sum_>
+
+ + +
270 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
+ +
272 const AggregateAcrossGenesOptions& options)
+
273{
+
274 if (input.prefer_rows()) {
+
275 aggregate_across_genes_internal::compute_aggregate_by_row(input, gene_sets, buffers, options);
+
276 } else {
+
277 aggregate_across_genes_internal::compute_aggregate_by_column(input, gene_sets, buffers, options);
+
278 }
+
279
+
280 if (options.average) {
+
281 size_t nsets = gene_sets.size();
+
282 tatami::parallelize([&](int, size_t start, size_t length) {
+
283 size_t NC = input.ncol();
+
284 for (size_t s = start, end = start + length; s < end; ++s) {
+
285 const auto& set = gene_sets[s];
+
286 auto set_size = std::get<0>(set);
+
287
+
288 Sum_ denom = 0;
+
289 auto set_weights = std::get<2>(set);
+
290 if (set_weights) {
+
291 denom = std::accumulate(set_weights, set_weights + set_size, static_cast<Sum_>(0));
+
292 } else {
+
293 denom = set_size;
+
294 }
295
-
296 if (options.average) {
-
297 size_t nsets = gene_sets.size();
-
298 tatami::parallelize([&](int, size_t start, size_t length) {
-
299 size_t NC = input.ncol();
-
300 for (size_t s = start, end = start + length; s < end; ++s) {
-
301 const auto& set = gene_sets[s];
-
302 auto set_size = std::get<0>(set);
-
303
-
304 Sum_ denom = 0;
-
305 auto set_weights = std::get<2>(set);
-
306 if (set_weights) {
-
307 denom = std::accumulate(set_weights, set_weights + set_size, static_cast<Sum_>(0));
-
308 } else {
-
309 denom = set_size;
-
310 }
-
311
-
312 auto current = buffers.sum[s];
-
313 for (size_t c = 0; c < NC; ++c) {
-
314 current[c] /= denom;
-
315 }
-
316 }
-
317 }, nsets, options.num_threads);
-
318 }
-
319}
+
296 auto current = buffers.sum[s];
+
297 for (size_t c = 0; c < NC; ++c) {
+
298 current[c] /= denom;
+
299 }
+
300 }
+
301 }, nsets, options.num_threads);
+
302 }
+
303}
-
320
-
340template<typename Sum_ = double, typename Data_, typename Index_, typename Gene_, typename Weight_>
-
- - -
343 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
-
344 const AggregateAcrossGenesOptions& options)
-
345{
- - -
348
-
349 size_t NC = input.ncol();
-
350 size_t nsets = gene_sets.size();
-
351 output.sum.resize(nsets);
-
352 buffers.sum.resize(nsets);
-
353
-
354 for (size_t s = 0; s < nsets; ++s) {
-
355 output.sum[s].resize(NC
-
356#ifdef SCRAN_AGGREGATE_TEST_INIT
-
357 , SCRAN_AGGREGATE_TEST_INIT
-
358#endif
-
359 );
-
360 buffers.sum[s] = output.sum[s].data();
-
361 }
-
362
-
363 aggregate_across_genes(input, gene_sets, buffers, options);
-
364 return output;
-
365}
+
304
+
324template<typename Sum_ = double, typename Data_, typename Index_, typename Gene_, typename Weight_>
+
+ + +
327 const std::vector<std::tuple<size_t, const Gene_*, const Weight_*> >& gene_sets,
+
328 const AggregateAcrossGenesOptions& options)
+
329{
+ + +
332
+
333 size_t NC = input.ncol();
+
334 size_t nsets = gene_sets.size();
+
335 output.sum.resize(nsets);
+
336 buffers.sum.resize(nsets);
+
337
+
338 for (size_t s = 0; s < nsets; ++s) {
+
339 output.sum[s].resize(NC
+
340#ifdef SCRAN_AGGREGATE_TEST_INIT
+
341 , SCRAN_AGGREGATE_TEST_INIT
+
342#endif
+
343 );
+
344 buffers.sum[s] = output.sum[s].data();
+
345 }
+
346
+
347 aggregate_across_genes(input, gene_sets, buffers, options);
+
348 return output;
+
349}
-
366
-
367}
-
368
-
369#endif
+
350
+
351}
+
352
+
353#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
virtual std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const=0
-
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:14
-
void aggregate_across_genes(const tatami::Matrix< Data_, Index_ > &input, const std::vector< std::tuple< size_t, const Gene_ *, const Weight_ * > > &gene_sets, const AggregateAcrossGenesBuffers< Sum_ > &buffers, const AggregateAcrossGenesOptions &options)
Definition aggregate_across_genes.hpp:284
+
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:15
+
void aggregate_across_genes(const tatami::Matrix< Data_, Index_ > &input, const std::vector< std::tuple< size_t, const Gene_ *, const Weight_ * > > &gene_sets, const AggregateAcrossGenesBuffers< Sum_ > &buffers, const AggregateAcrossGenesOptions &options)
Definition aggregate_across_genes.hpp:268
void parallelize(Function_ fun, Index_ tasks, int threads)
std::shared_ptr< const std::vector< Index_ > > VectorPtr
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
-
Buffers for aggregate_across_genes().
Definition aggregate_across_genes.hpp:40
-
std::vector< Sum_ * > sum
Definition aggregate_across_genes.hpp:46
-
Options for aggregate_across_genes().
Definition aggregate_across_genes.hpp:21
-
bool average
Definition aggregate_across_genes.hpp:32
-
int num_threads
Definition aggregate_across_genes.hpp:26
-
Results of aggregate_across_genes().
Definition aggregate_across_genes.hpp:54
-
std::vector< std::vector< Sum_ > > sum
Definition aggregate_across_genes.hpp:60
+
Buffers for aggregate_across_genes().
Definition aggregate_across_genes.hpp:41
+
std::vector< Sum_ * > sum
Definition aggregate_across_genes.hpp:47
+
Options for aggregate_across_genes().
Definition aggregate_across_genes.hpp:22
+
bool average
Definition aggregate_across_genes.hpp:33
+
int num_threads
Definition aggregate_across_genes.hpp:27
+
Results of aggregate_across_genes().
Definition aggregate_across_genes.hpp:55
+
std::vector< std::vector< Sum_ > > sum
Definition aggregate_across_genes.hpp:61
diff --git a/docs/clean__factor_8hpp_source.html b/docs/clean__factor_8hpp_source.html index 3a9db58..fa597c9 100644 --- a/docs/clean__factor_8hpp_source.html +++ b/docs/clean__factor_8hpp_source.html @@ -140,7 +140,7 @@
68}
69
70#endif
-
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:14
+
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:15
std::vector< Factor_ > clean_factor(size_t n, const Factor_ *factor, Output_ *cleaned)
Definition clean_factor.hpp:33
diff --git a/docs/combine__factors_8hpp_source.html b/docs/combine__factors_8hpp_source.html index 7ba081c..869cec5 100644 --- a/docs/combine__factors_8hpp_source.html +++ b/docs/combine__factors_8hpp_source.html @@ -255,7 +255,7 @@
206
207#endif
Clean up a categorical factor.
-
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:14
+
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:15
std::vector< std::vector< Factor_ > > combine_factors_unused(size_t n, const std::vector< std::pair< const Factor_ *, Number_ > > &factors, Combined_ *combined)
Definition combine_factors.hpp:146
std::vector< Factor_ > clean_factor(size_t n, const Factor_ *factor, Output_ *cleaned)
Definition clean_factor.hpp:33
std::vector< std::vector< Factor_ > > combine_factors(size_t n, const std::vector< const Factor_ * > &factors, Combined_ *combined)
Definition combine_factors.hpp:40
diff --git a/docs/index.html b/docs/index.html index 2fc0162..9555821 100644 --- a/docs/index.html +++ b/docs/index.html @@ -98,9 +98,9 @@

Quick start

res.sums[0]; // vector of sums for the first group across genes.
res.detected; // vector of vectors of the number of detected cells per gene.
-
void aggregate_across_cells(const tatami::Matrix< Data_, Index_ > &input, const Factor_ *factor, const AggregateAcrossCellsBuffers< Sum_, Detected_ > &buffers, const AggregateAcrossCellsOptions &options)
Definition aggregate_across_cells.hpp:285
+
void aggregate_across_cells(const tatami::Matrix< Data_, Index_ > &input, const Factor_ *factor, const AggregateAcrossCellsBuffers< Sum_, Detected_ > &buffers, const AggregateAcrossCellsOptions &options)
Definition aggregate_across_cells.hpp:256
Aggregate single-cell expression values.
-
Options for aggregate_across_cells().
Definition aggregate_across_cells.hpp:19
+
Options for aggregate_across_cells().
Definition aggregate_across_cells.hpp:20

The array of groupings should contain integer assignments to groups 0, 1, 2, etc. For more complex groupings defined from combinations of multiple factors, the combine_factors() utility will create group assignments from unique combinations of those factors:

std::vector<int> grouping1 { 0, 0, 1, 1, 2, 2 };
std::vector<int> grouping2 { 0, 1, 0, 1, 0, 1 };
@@ -133,8 +133,8 @@

Quick start

g_opt
);
g_res.sum[0]; // vector of sums for set 1 in each cell.
-
void aggregate_across_genes(const tatami::Matrix< Data_, Index_ > &input, const std::vector< std::tuple< size_t, const Gene_ *, const Weight_ * > > &gene_sets, const AggregateAcrossGenesBuffers< Sum_ > &buffers, const AggregateAcrossGenesOptions &options)
Definition aggregate_across_genes.hpp:284
-
Options for aggregate_across_genes().
Definition aggregate_across_genes.hpp:21
+
void aggregate_across_genes(const tatami::Matrix< Data_, Index_ > &input, const std::vector< std::tuple< size_t, const Gene_ *, const Weight_ * > > &gene_sets, const AggregateAcrossGenesBuffers< Sum_ > &buffers, const AggregateAcrossGenesOptions &options)
Definition aggregate_across_genes.hpp:268
+
Options for aggregate_across_genes().
Definition aggregate_across_genes.hpp:22

Check out the reference documentation for more details.

Building projects

CMake with FetchContent

diff --git a/docs/scran__aggregate_8hpp.html b/docs/scran__aggregate_8hpp.html index 802b357..c41fffa 100644 --- a/docs/scran__aggregate_8hpp.html +++ b/docs/scran__aggregate_8hpp.html @@ -99,40 +99,43 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/docs/scran__aggregate_8hpp__incl.map b/docs/scran__aggregate_8hpp__incl.map index 7b9209a..b6998f2 100644 --- a/docs/scran__aggregate_8hpp__incl.map +++ b/docs/scran__aggregate_8hpp__incl.map @@ -1,36 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/scran__aggregate_8hpp__incl.md5 b/docs/scran__aggregate_8hpp__incl.md5 index e207dc6..11c2abe 100644 --- a/docs/scran__aggregate_8hpp__incl.md5 +++ b/docs/scran__aggregate_8hpp__incl.md5 @@ -1 +1 @@ -057cad491b4332cd20858706b182e94c \ No newline at end of file +347a02aca69c266782aba6564ee61fdb \ No newline at end of file diff --git a/docs/scran__aggregate_8hpp__incl.png b/docs/scran__aggregate_8hpp__incl.png index 33f7c52..f2d1194 100644 Binary files a/docs/scran__aggregate_8hpp__incl.png and b/docs/scran__aggregate_8hpp__incl.png differ diff --git a/docs/scran__aggregate_8hpp_source.html b/docs/scran__aggregate_8hpp_source.html index edbabd5..cefa12f 100644 --- a/docs/scran__aggregate_8hpp_source.html +++ b/docs/scran__aggregate_8hpp_source.html @@ -105,7 +105,7 @@
Aggregate expression values across genes.
Clean up a categorical factor.
Combine categorical factors into a single factor.
-
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:14
+
Aggregate single-cell expression values.
Definition aggregate_across_cells.hpp:15