48 SearchStrand
strand1 = SearchStrand::FORWARD;
59 SearchStrand
strand2 = SearchStrand::FORWARD;
93 const char* template_seq1,
size_t template_length1,
const BarcodePool& barcode_pool1,
94 const char* template_seq2,
size_t template_length2,
const BarcodePool& barcode_pool2,
97 search_reverse1(search_reverse(options.strand1)),
98 search_reverse2(search_reverse(options.strand2)),
99 constant1(template_seq1, template_length1, options.strand1),
100 constant2(template_seq2, template_length2, options.strand2),
101 max_mm1(options.max_mismatches1),
102 max_mm2(options.max_mismatches2),
103 randomized(options.random),
104 use_first(options.use_first)
106 auto num_options = barcode_pool1.
size();
107 if (num_options != barcode_pool2.
size()) {
108 throw std::runtime_error(
"both barcode pools should be of the same length");
110 counts.resize(num_options);
114 const auto& regions = constant1.variable_regions();
115 if (regions.size() != 1) {
116 throw std::runtime_error(
"expected one variable region in the first constant template");
118 len1 = regions[0].second - regions[0].first;
119 if (len1 != barcode_pool1.
length) {
120 throw std::runtime_error(
"length of variable sequences (" + std::to_string(barcode_pool1.
length) +
121 ") should be the same as the variable region (" + std::to_string(len1) +
")");
127 const auto& regions = constant2.variable_regions();
128 if (regions.size() != 1) {
129 throw std::runtime_error(
"expected one variable region in the second constant template");
131 len2 = regions[0].second - regions[0].first;
132 if (len2 != barcode_pool2.
length) {
133 throw std::runtime_error(
"length of variable sequences (" + std::to_string(barcode_pool2.
length) +
134 ") should be the same as the variable region (" + std::to_string(len2) +
")");
139 std::vector<std::string> combined;
140 combined.reserve(num_options);
142 for (
size_t i = 0; i < num_options; ++i) {
145 auto ptr1 = barcode_pool1[i];
146 if (search_reverse1) {
147 for (
size_t j = 0; j < len1; ++j) {
148 current += complement_base<true, true>(ptr1[len1 - j - 1]);
151 current.insert(current.end(), ptr1, ptr1 + len1);
154 auto ptr2 = barcode_pool2[i];
155 if (search_reverse2) {
156 for (
size_t j = 0; j < len2; ++j) {
157 current += complement_base<true, true>(ptr2[len2 - j - 1]);
160 current.insert(current.end(), ptr2, ptr2 + len2);
163 combined.push_back(std::move(current));
170 std::array<int, 2>{
static_cast<int>(len1),
static_cast<int>(len2) },
186 State(
size_t n = 0) : counts(n) {}
187 std::vector<int> counts;
190 std::pair<std::string, int> first_match;
191 std::vector<std::pair<std::string, int> > second_matches;
192 std::string combined;
195 typename SegmentedBarcodeSearch<2>::State details;
198 State initialize()
const {
199 return State(counts.size());
202 void reduce(State& s) {
204 for (
size_t i = 0; i < counts.size(); ++i) {
205 counts[i] += s.counts[i];
210 constexpr static bool use_names =
false;
216 static void fill_store(std::pair<std::string, int>& first_match,
const char* start,
const char* end,
int mm) {
217 first_match.first.clear();
218 first_match.first.insert(first_match.first.end(), start, end);
219 first_match.second = mm;
223 static void fill_store(std::vector<std::pair<std::string, int> >& second_matches,
const char* start,
const char* end,
int mm) {
224 second_matches.emplace_back(std::string(start, end), mm);
228 template<
class Store>
229 static bool inner_process(
231 const ScanTemplate<max_size>& constant,
234 typename ScanTemplate<max_size>::State& deets,
237 while (!deets.finished) {
238 constant.next(deets);
240 if (deets.reverse_mismatches <= max_mm) {
241 const auto& reg = constant.template variable_regions<true>()[0];
242 auto start = against + deets.position;
243 fill_store(store, start + reg.first, start + reg.second, deets.reverse_mismatches);
247 if (deets.forward_mismatches <= max_mm) {
248 const auto& reg = constant.variable_regions()[0];
249 auto start = against + deets.position;
250 fill_store(store, start + reg.first, start + reg.second, deets.forward_mismatches);
258 bool process_first(State& state,
const std::pair<const char*, const char*>& against1,
const std::pair<const char*, const char*>& against2)
const {
259 auto deets1 = constant1.initialize(against1.first, against1.second - against1.first);
260 auto deets2 = constant2.initialize(against2.first, against2.second - against2.first);
262 state.second_matches.clear();
264 auto checker = [&](
size_t idx2) ->
bool {
265 const auto& current2 = state.second_matches[idx2];
266 state.combined = state.first_match.first;
267 state.combined += current2.first;
268 varlib.
search(state.combined, state.details, std::array<int, 2>{ max_mm1 - state.first_match.second, max_mm2 - current2.second });
270 if (state.details.index >= 0) {
271 ++state.counts[state.details.index];
283 while (inner_process(search_reverse1, constant1, max_mm1, against1.first, deets1, state.first_match)) {
284 if (!deets2.finished) {
288 while (inner_process(search_reverse2, constant2, max_mm2, against2.first, deets2, state.second_matches)) {
289 if (checker(state.second_matches.size() - 1)) {
293 if (state.second_matches.empty()) {
299 for (
size_t i = 0; i < state.second_matches.size(); ++i) {
310 std::pair<int, int> process_best(State& state,
const std::pair<const char*, const char*>& against1,
const std::pair<const char*, const char*>& against2)
const {
311 auto deets1 = constant1.initialize(against1.first, against1.second - against1.first);
312 auto deets2 = constant2.initialize(against2.first, against2.second - against2.first);
317 state.second_matches.clear();
318 while (inner_process(search_reverse2, constant2, max_mm2, against2.first, deets2, state.second_matches)) {}
321 int best_mismatches = max_mm1 + max_mm2 + 1;
322 size_t num_second_matches = state.second_matches.size();
324 if (!state.second_matches.empty()) {
325 while (inner_process(search_reverse1, constant1, max_mm1, against1.first, deets1, state.first_match)) {
326 for (
size_t i = 0; i < num_second_matches; ++i) {
327 const auto& current2 = state.second_matches[i];
329 state.combined = state.first_match.first;
330 state.combined += current2.first;
331 varlib.search(state.combined, state.details, std::array<int, 2>{ max_mm1 - state.first_match.second, max_mm2 - current2.second });
333 if (state.details.index >= 0) {
334 int cur_mismatches = state.details.mismatches + state.first_match.second + current2.second;
335 if (cur_mismatches < best_mismatches) {
336 chosen = state.details.index;
337 best_mismatches = cur_mismatches;
338 }
else if (cur_mismatches == best_mismatches && chosen != state.details.index) {
346 return std::make_pair(chosen, best_mismatches);
353 bool process(State& state,
const std::pair<const char*, const char*>& r1,
const std::pair<const char*, const char*>& r2)
const {
357 found = process_first(state, r1, r2);
358 if (!found && randomized) {
359 found = process_first(state, r2, r1);
363 auto best = process_best(state, r1, r2);
365 auto best2 = process_best(state, r2, r1);
366 if (best.first < 0 || best.second > best2.second) {
368 }
else if (best.second == best2.second && best.first != best2.first) {
373 found = best.first >= 0;
375 ++state.counts[best.first];
387 bool search_reverse1, search_reverse2;
389 ScanTemplate<max_size> constant1, constant2;
390 SegmentedBarcodeSearch<2> varlib;
391 int max_mm1, max_mm2;
394 bool use_first =
true;
396 std::vector<int> counts;