97        my_search_reverse1(search_reverse(options.strand1)),
 
   98        my_search_reverse2(search_reverse(options.strand2)),
 
   99        my_constant1(template_seq1, template_length1, options.strand1),
 
  100        my_constant2(template_seq2, template_length2, options.strand2),
 
  101        my_max_mm1(options.max_mismatches1),
 
  102        my_max_mm2(options.max_mismatches2),
 
  103        my_randomized(options.random),
 
  104        my_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        my_counts.resize(num_options);
 
  114            const auto& regions = my_constant1.forward_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 = my_constant2.forward_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);
 
  145            auto ptr1 = barcode_pool1[i];
 
  146            if (my_search_reverse1) {
 
  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 (my_search_reverse2) {
 
  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));
 
  167        BarcodePool combined_set(combined);
 
  168        my_varlib = SegmentedBarcodeSearch<2>(
 
  170            std::array<SeqLength, 2>{ len1, len2 }, 
 
  172                typename SegmentedBarcodeSearch<2>::Options bopt;
 
  173                bopt.max_mismatches = { my_max_mm1, my_max_mm2 };
 
  174                bopt.duplicates = options.duplicates;
 
  175                bopt.reverse = 
false; 
 
 
  182    bool my_search_reverse1, my_search_reverse2;
 
  184    ScanTemplate<max_size_> my_constant1, my_constant2;
 
  185    SegmentedBarcodeSearch<2> my_varlib;
 
  186    int my_max_mm1, my_max_mm2;
 
  189    bool my_use_first = 
true;
 
  191    std::vector<Count> my_counts;
 
  200        State(
typename std::vector<Count>::size_type n) : counts(n) {}
 
  202        std::vector<Count> counts;
 
  205        std::pair<std::string, int> first_match;
 
  206        std::vector<std::pair<std::string, int> > second_matches;
 
  207        std::string combined;
 
  210        typename SegmentedBarcodeSearch<2>::State details;
 
  213    State initialize()
 const {
 
  214        return State(my_counts.size());
 
  217    void reduce(State& s) {
 
  218        my_varlib.reduce(s.details);
 
  219        auto csize = my_counts.size();
 
  220        for (
decltype(csize) i = 0; i < csize; ++i) {
 
  221            my_counts[i] += s.counts[i];
 
  226    constexpr static bool use_names = 
false;
 
  232    static void fill_store(std::pair<std::string, int>& first_match, 
const char* start, 
const char* end, 
int mm) {
 
  233        first_match.first.clear();
 
  234        first_match.first.insert(first_match.first.end(), start, end);
 
  235        first_match.second = mm;
 
  239    static void fill_store(std::vector<std::pair<std::string, int> >& second_matches, 
const char* start, 
const char* end, 
int mm) {
 
  240        second_matches.emplace_back(std::string(start, end), mm);
 
  244    template<
class Store>
 
  245    static bool inner_process(
 
  247        const ScanTemplate<max_size_>& constant, 
 
  250        typename ScanTemplate<max_size_>::State& deets,
 
  253        while (!deets.finished) {
 
  254            constant.next(deets);
 
  256                if (deets.reverse_mismatches <= max_mm) {
 
  257                    const auto& reg = constant.reverse_variable_regions()[0];
 
  258                    auto start = against + deets.position;
 
  259                    fill_store(store, start + reg.first, start + reg.second, deets.reverse_mismatches);
 
  263                if (deets.forward_mismatches <= max_mm) {
 
  264                    const auto& reg = constant.forward_variable_regions()[0];
 
  265                    auto start = against + deets.position;
 
  266                    fill_store(store, start + reg.first, start + reg.second, deets.forward_mismatches);
 
  274    bool process_first(State& state, 
const std::pair<const char*, const char*>& against1, 
const std::pair<const char*, const char*>& against2)
 const {
 
  275        auto deets1 = my_constant1.initialize(against1.first, against1.second - against1.first);
 
  276        auto deets2 = my_constant2.initialize(against2.first, against2.second - against2.first);
 
  278        state.second_matches.clear();
 
  279        typedef decltype(state.second_matches.size()) Size;
 
  281        auto checker = [&](Size idx2) -> 
bool {
 
  282            const auto& current2 = state.second_matches[idx2];
 
  283            state.combined = state.first_match.first;
 
  284            state.combined += current2.first; 
 
  285            my_varlib.search(state.combined, state.details, std::array<int, 2>{ my_max_mm1 - state.first_match.second, my_max_mm2 - current2.second });
 
  288                ++state.counts[state.details.index];
 
  300        while (inner_process(my_search_reverse1, my_constant1, my_max_mm1, against1.first, deets1, state.first_match)) {
 
  301            if (!deets2.finished) {
 
  305                while (inner_process(my_search_reverse2, my_constant2, my_max_mm2, against2.first, deets2, state.second_matches)) {
 
  306                    if (checker(state.second_matches.size() - 1)) {
 
  310                if (state.second_matches.empty()) {
 
  316                for (Size i = 0, end = state.second_matches.size(); i < end; ++i) {
 
  327    std::pair<BarcodeIndex, int> process_best(State& state, 
const std::pair<const char*, const char*>& against1, 
const std::pair<const char*, const char*>& against2)
 const {
 
  328        auto deets1 = my_constant1.initialize(against1.first, against1.second - against1.first);
 
  329        auto deets2 = my_constant2.initialize(against2.first, against2.second - against2.first);
 
  334        state.second_matches.clear();
 
  335        while (inner_process(my_search_reverse2, my_constant2, my_max_mm2, against2.first, deets2, state.second_matches)) {}
 
  338        int best_mismatches = my_max_mm1 + my_max_mm2 + 1;
 
  339        auto num_second_matches = state.second_matches.size();
 
  341        if (!state.second_matches.empty()) {
 
  342            while (inner_process(my_search_reverse1, my_constant1, my_max_mm1, against1.first, deets1, state.first_match)) {
 
  343                for (
decltype(num_second_matches) i = 0; i < num_second_matches; ++i) {
 
  344                    const auto& current2 = state.second_matches[i];
 
  346                    state.combined = state.first_match.first;
 
  347                    state.combined += current2.first; 
 
  348                    my_varlib.search(state.combined, state.details, std::array<int, 2>{ my_max_mm1 - state.first_match.second, my_max_mm2 - current2.second });
 
  351                        int cur_mismatches = state.details.mismatches + state.first_match.second + current2.second;
 
  352                        if (cur_mismatches < best_mismatches) {
 
  353                            chosen = state.details.index;
 
  354                            best_mismatches = cur_mismatches;
 
  355                        } 
else if (cur_mismatches == best_mismatches && chosen != state.details.index) { 
 
  363        return std::make_pair(chosen, best_mismatches);
 
  370    bool process(State& state, 
const std::pair<const char*, const char*>& r1, 
const std::pair<const char*, const char*>& r2)
 const {
 
  374            found = process_first(state, r1, r2);
 
  375            if (!found && my_randomized) {
 
  376                found = process_first(state, r2, r1);
 
  380            auto best = process_best(state, r1, r2);
 
  382                auto best2 = process_best(state, r2, r1);
 
  385                } 
else if (best.second == best2.second && best.first != best2.first) {
 
  392                ++state.counts[best.first];