50 SearchStrand
strand = SearchStrand::FORWARD;
70 template<
class BarcodePoolContainer>
72 forward(search_forward(options.strand)),
73 reverse(search_reverse(options.strand)),
74 max_mm(options.max_mismatches),
75 use_first(options.use_first),
76 constant_matcher(template_seq, template_length, options.strand)
78 const auto& regions = constant_matcher.variable_regions();
79 if (regions.size() != num_variable) {
80 throw std::runtime_error(
"expected " + std::to_string(num_variable) +
" variable regions in the constant template");
82 if (barcode_pools.size() != num_variable) {
83 throw std::runtime_error(
"length of 'barcode_pools' should be equal to the number of variable regions");
86 for (
size_t i = 0; i < num_variable; ++i) {
87 size_t rlen = regions[i].second - regions[i].first;
88 size_t vlen = barcode_pools[i].length;
90 throw std::runtime_error(
"length of variable region " + std::to_string(i + 1) +
" (" + std::to_string(rlen) +
91 ") should be the same as its sequences (" + std::to_string(vlen) +
")");
96 for (
size_t i = 0; i < num_variable; ++i) {
97 num_options[i] = barcode_pools[i].pool.size();
106 for (
size_t i = 0; i < num_variable; ++i) {
113 for (
size_t i = 0; i < num_variable; ++i) {
135 std::vector<std::array<int, num_variable> >collected;
138 std::array<int, num_variable> temp;
142 std::array<typename SimpleBarcodeSearch::State, num_variable> forward_details, reverse_details;
149 template<
bool reverse>
150 std::pair<bool, int> find_match(
154 const std::array<SimpleBarcodeSearch, num_variable>& libs,
155 std::array<typename SimpleBarcodeSearch::State, num_variable>& states,
156 std::array<int, num_variable>& temp,
159 const auto& regions = constant_matcher.template variable_regions<reverse>();
161 for (
size_t r = 0; r < num_variable; ++r) {
162 auto range = regions[r];
163 auto start = seq + position;
165 buffer.insert(buffer.end(), start + range.first, start + range.second);
167 auto& curstate = states[r];
168 libs[r].search(buffer, curstate, max_mm - obs_mismatches);
169 if (curstate.index < 0) {
170 return std::make_pair(
false, 0);
173 obs_mismatches += curstate.mismatches;
174 if (obs_mismatches > max_mm) {
175 return std::make_pair(
false, 0);
178 if constexpr(reverse) {
179 temp[num_variable - r - 1] = curstate.index;
181 temp[r] = curstate.index;
185 return std::make_pair(
true, obs_mismatches);
188 std::pair<bool, int> forward_match(
const char* seq,
const typename ScanTemplate<max_size>::State& deets, State& state)
const {
189 return find_match<false>(seq, deets.position, deets.forward_mismatches, forward_lib, state.forward_details, state.temp, state.buffer);
192 std::pair<bool, int> reverse_match(
const char* seq,
const typename ScanTemplate<max_size>::State& deets, State& state)
const {
193 return find_match<true>(seq, deets.position, deets.reverse_mismatches, reverse_lib, state.reverse_details, state.temp, state.buffer);
197 void process_first(State& state,
const std::pair<const char*, const char*>& x)
const {
198 auto deets = constant_matcher.initialize(x.first, x.second - x.first);
200 while (!deets.finished) {
201 constant_matcher.next(deets);
203 if (forward && deets.forward_mismatches <= max_mm) {
204 if (forward_match(x.first, deets, state).first) {
205 state.collected.push_back(state.temp);
210 if (reverse && deets.reverse_mismatches <= max_mm) {
211 if (reverse_match(x.first, deets, state).first) {
212 state.collected.push_back(state.temp);
219 void process_best(State& state,
const std::pair<const char*, const char*>& x)
const {
220 auto deets = constant_matcher.initialize(x.first, x.second - x.first);
222 int best_mismatches = max_mm + 1;
223 std::array<int, num_variable> best_id;
225 auto update = [&](std::pair<bool, int> match) ->
void {
226 if (match.first && match.second <= best_mismatches) {
227 if (match.second == best_mismatches) {
228 if (best_id != state.temp) {
237 best_mismatches = match.second;
238 best_id = state.temp;
243 while (!deets.finished) {
244 constant_matcher.next(deets);
246 if (forward && deets.forward_mismatches <= max_mm) {
247 update(forward_match(x.first, deets, state));
250 if (reverse && deets.reverse_mismatches <= max_mm) {
251 update(reverse_match(x.first, deets, state));
256 state.collected.push_back(best_id);
264 State initialize()
const {
268 void reduce(State& s) {
270 for (
size_t r = 0; r < num_variable; ++r) {
271 forward_lib[r].reduce(s.forward_details[r]);
275 for (
size_t r = 0; r < num_variable; ++r) {
276 reverse_lib[r].reduce(s.reverse_details[r]);
280 combinations.insert(combinations.end(), s.collected.begin(), s.collected.end());
285 void process(State& state,
const std::pair<const char*, const char*>& x)
const {
287 process_first(state, x);
289 process_best(state, x);
294 static constexpr bool use_names =
false;
304 sort_combinations(combinations, num_options);
328 std::array<SimpleBarcodeSearch, num_variable> forward_lib, reverse_lib;
329 std::array<size_t, num_variable> num_options;
331 std::vector<std::array<int, num_variable> > combinations;