From 7696766a73df1914e58614ebe0c48cfe9af6a0ff Mon Sep 17 00:00:00 2001 From: Alaa Abdel Latif Date: Thu, 4 Feb 2021 19:11:36 -0800 Subject: [PATCH 1/4] added optional -x flag for ivar trim. allows trimming of reads that occur at a specified offset position relative to the primer sequence positions --- configure.ac | 2 +- src/ivar.cpp | 12 +++++++++--- src/primer_bed.cpp | 6 +++--- src/primer_bed.h | 2 +- src/trim_primer_quality.cpp | 4 ++-- src/trim_primer_quality.h | 2 +- tests/test_amplicon_search.cpp | 7 ++++--- tests/test_isize_trim.cpp | 3 ++- tests/test_primer_bed.cpp | 3 ++- tests/test_primer_trim.cpp | 3 ++- tests/test_primer_trim_edge_cases.cpp | 3 ++- tests/test_trim.cpp | 3 ++- tests/test_unpaired_trim.cpp | 3 ++- 13 files changed, 33 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index ad994ac1..c4eb867e 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) -AC_INIT([ivar], [1.3], [gkarthik@scripps.edu]) +AC_INIT([ivar], [1.3.1], [gkarthik@scripps.edu]) AM_INIT_AUTOMAKE([foreign subdir-objects]) AC_CONFIG_HEADERS([config.h]) diff --git a/src/ivar.cpp b/src/ivar.cpp index 161f4c02..0ef226c1 100755 --- a/src/ivar.cpp +++ b/src/ivar.cpp @@ -16,7 +16,7 @@ #include "suffix_tree.h" #include "get_common_variants.h" -const std::string VERSION = "1.3"; +const std::string VERSION = "1.3.1"; struct args_t { std::string bam; // -i @@ -37,6 +37,7 @@ struct args_t { char gap; // -n bool keep_min_coverage; // -k std::string primer_pair_file; // -f + int32_t primer_offset; // -x std::string file_list; // -f bool write_no_primers_flag; // -e std::string gff; // -g @@ -67,6 +68,7 @@ void print_trim_usage(){ " -b BED file with primer sequences and positions. If no BED file is specified, only quality trimming will be done.\n" " -f [EXPERIMENTAL] Primer pair information file containing left and right primer names for the same amplicon separated by a tab\n" " If provided, reads that do not fall within atleat one amplicon will be ignored prior to primer trimming.\n" + " -x Primer position offset (Default: 0). Reads that occur at the specified offset positions relative to primer positions will also be trimmed.\n" " -m Minimum length of read to retain after trimming (Default: 30)\n" " -q Minimum quality threshold for sliding window to pass (Default: 20)\n" " -s Width of sliding window (Default: 4)\n" @@ -165,7 +167,7 @@ void print_version_info(){ "\nPlease raise issues and bug reports at https://github.com/andersen-lab/ivar/\n\n"; } -static const char *trim_opt_str = "i:b:f:p:m:q:s:ekh?"; +static const char *trim_opt_str = "i:b:f:x:p:m:q:s:ekh?"; static const char *variants_opt_str = "p:t:q:m:r:g:h?"; static const char *consensus_opt_str = "i:p:q:t:m:n:kh?"; static const char *removereads_opt_str = "i:p:t:b:h?"; @@ -221,6 +223,7 @@ int main(int argc, char* argv[]){ g_args.keep_for_reanalysis = false; g_args.bed = ""; g_args.primer_pair_file = ""; + g_args.primer_offset = 0; opt = getopt( argc, argv, trim_opt_str); while( opt != -1 ) { switch( opt ) { @@ -232,6 +235,9 @@ int main(int argc, char* argv[]){ break; case 'f': g_args.primer_pair_file = optarg; + break; + case 'x': + g_args.primer_offset = std::stoi(optarg); break; case 'p': g_args.prefix = optarg; @@ -264,7 +270,7 @@ int main(int argc, char* argv[]){ return -1; } g_args.prefix = get_filename_without_extension(g_args.prefix,".bam"); - res = trim_bam_qual_primer(g_args.bam, g_args.bed, g_args.prefix, g_args.region, g_args.min_qual, g_args.sliding_window, cl_cmd.str(), g_args.write_no_primers_flag, g_args.keep_for_reanalysis, g_args.min_length, g_args.primer_pair_file); + res = trim_bam_qual_primer(g_args.bam, g_args.bed, g_args.prefix, g_args.region, g_args.min_qual, g_args.sliding_window, cl_cmd.str(), g_args.write_no_primers_flag, g_args.keep_for_reanalysis, g_args.min_length, g_args.primer_pair_file, g_args.primer_offset); } // ivar variants else if (cmd.compare("variants") == 0){ diff --git a/src/primer_bed.cpp b/src/primer_bed.cpp index 16e38cee..4b38f9f6 100644 --- a/src/primer_bed.cpp +++ b/src/primer_bed.cpp @@ -85,7 +85,7 @@ void print_bed_format(){ std::cout << "It requires the following columns delimited by a tab: chrom, chromStart, chromEnd, name, score, strand" << std::endl; } -std::vector populate_from_file(std::string path){ +std::vector populate_from_file(std::string path, int32_t offset = 0){ std::ifstream data(path.c_str()); std::string line; std::vector primers; @@ -103,7 +103,7 @@ std::vector populate_from_file(std::string path){ break; case 1: if(std::all_of(cell.begin(), cell.end(), ::isdigit)) { - p.set_start(std::stoul(cell)); + p.set_start(std::stoul(cell) - offset); } else { print_bed_format(); primers.clear(); @@ -112,7 +112,7 @@ std::vector populate_from_file(std::string path){ break; case 2: if(std::all_of(cell.begin(), cell.end(), ::isdigit)) { - p.set_end(std::stoul(cell)-1); // Bed format - End is not 0 based + p.set_end(std::stoul(cell) - 1 + offset); // Bed format - End is not 0 based } else { print_bed_format(); primers.clear(); diff --git a/src/primer_bed.h b/src/primer_bed.h index 2ff284ec..4e064085 100644 --- a/src/primer_bed.h +++ b/src/primer_bed.h @@ -46,7 +46,7 @@ class primer { }; -std::vector populate_from_file(std::string path); +std::vector populate_from_file(std::string path, int32_t offset); std::vector get_primers(std::vector p, unsigned int pos); int get_primer_indice(std::vector p, std::string name); int populate_pair_indices(std::vector &primers, std::string path); diff --git a/src/trim_primer_quality.cpp b/src/trim_primer_quality.cpp index 38db3d9d..5d73b5a0 100755 --- a/src/trim_primer_quality.cpp +++ b/src/trim_primer_quality.cpp @@ -346,12 +346,12 @@ bool amplicon_filter(IntervalTree amplicons, bam1_t* r){ return amplicon_flag; } -int trim_bam_qual_primer(std::string bam, std::string bed, std::string bam_out, std::string region_, uint8_t min_qual, uint8_t sliding_window, std::string cmd, bool write_no_primer_reads, bool keep_for_reanalysis, int min_length = 30, std::string pair_info = "") { +int trim_bam_qual_primer(std::string bam, std::string bed, std::string bam_out, std::string region_, uint8_t min_qual, uint8_t sliding_window, std::string cmd, bool write_no_primer_reads, bool keep_for_reanalysis, int min_length = 30, std::string pair_info = "", int32_t primer_offset = 0) { int retval = 0; std::vector primers; int max_primer_len = 0; if(!bed.empty()){ - primers = populate_from_file(bed); + primers = populate_from_file(bed, primer_offset); if(primers.size() == 0){ std::cout << "Exiting." << std::endl; return -1; diff --git a/src/trim_primer_quality.h b/src/trim_primer_quality.h index dd08ba0b..3fe1f82b 100755 --- a/src/trim_primer_quality.h +++ b/src/trim_primer_quality.h @@ -31,7 +31,7 @@ inline void free_cigar(cigar_ t) { if (t.free_cig) free(t.cigar); } void add_pg_line_to_header(bam_hdr_t** hdr, char *cmd); -int trim_bam_qual_primer(std::string bam, std::string bed, std::string bam_out, std::string region_, uint8_t min_qual, uint8_t sliding_window, std::string cmd, bool write_no_primer_reads, bool mark_qcfail_flag, int min_length, std::string pair_info); +int trim_bam_qual_primer(std::string bam, std::string bed, std::string bam_out, std::string region_, uint8_t min_qual, uint8_t sliding_window, std::string cmd, bool write_no_primer_reads, bool mark_qcfail_flag, int min_length, std::string pair_info, int32_t primer_offset); void free_cigar(cigar_ t); int32_t get_pos_on_query(uint32_t *cigar, uint32_t ncigar, int32_t pos, int32_t ref_start); int32_t get_pos_on_reference(uint32_t *cigar, uint32_t ncigar, uint32_t pos, uint32_t ref_start); diff --git a/tests/test_amplicon_search.cpp b/tests/test_amplicon_search.cpp index 5bd705a6..ef4fba9a 100755 --- a/tests/test_amplicon_search.cpp +++ b/tests/test_amplicon_search.cpp @@ -5,11 +5,11 @@ #include "../src/primer_bed.h" #include "../src/interval_tree.h" -int test_amplicon_search(std::string bam_file, std::string bed_file, std::string pair_info_file, bool expected[]) +int test_amplicon_search(std::string bam_file, std::string bed_file, std::string pair_info_file, int32_t primer_offset, bool expected[]) { std::vector primers; IntervalTree amplicons; - primers = populate_from_file(bed_file); + primers = populate_from_file(bed_file, primer_offset); std::cout << "Total Number of primers: " << primers.size() << std::endl; amplicons = populate_amplicons(pair_info_file, primers); samFile *in = hts_open(bam_file.c_str(), "r"); @@ -35,13 +35,14 @@ int main(){ int success; std::string bam = "../data/test_amplicon.sorted.bam"; std::string pair_indice = "../data/pair_info_2.tsv"; + int32_t primer_offset = 0; std::string bed = "../data/test_isize.bed"; std::string prefix = "/tmp/data/trim_amplicon"; std::string bam_out = "/tmp/trim_amplicon.bam"; IntervalTree amplicons; bool expected[8] = {true, false, true, false, true, false, true, false}; - success = test_amplicon_search(bam, bed, pair_indice, expected); + success = test_amplicon_search(bam, bed, pair_indice, primer_offset, expected); amplicons.inOrder(); return success; } diff --git a/tests/test_isize_trim.cpp b/tests/test_isize_trim.cpp index 6deaf1fa..bfdd39bb 100755 --- a/tests/test_isize_trim.cpp +++ b/tests/test_isize_trim.cpp @@ -21,6 +21,7 @@ int test_isize_trim(uint8_t min_qual, uint8_t sliding_window, bool no_write_flag std::string bam = "../data/test_isize.sorted.bam"; std::string bed = "../data/test_isize.bed"; std::string pair_info = ""; + int32_t primer_offset = 0; std::string prefix = "../data/trim_isize"; std::string bam_out = "../data/trim_isize.bam"; @@ -29,7 +30,7 @@ int test_isize_trim(uint8_t min_qual, uint8_t sliding_window, bool no_write_flag std::string cmd = "@PG\tID:ivar-trim\tPN:ivar\tVN:1.0.0\tCL:ivar trim\n"; // Test and check result - res = trim_bam_qual_primer(bam, bed, prefix, region_, min_qual, sliding_window, cmd, no_write_flag, keep_for_reanalysis, min_length, pair_info); + res = trim_bam_qual_primer(bam, bed, prefix, region_, min_qual, sliding_window, cmd, no_write_flag, keep_for_reanalysis, min_length, pair_info, primer_offset); if (res) { success = -1; diff --git a/tests/test_primer_bed.cpp b/tests/test_primer_bed.cpp index f395a8e0..9581107a 100755 --- a/tests/test_primer_bed.cpp +++ b/tests/test_primer_bed.cpp @@ -7,7 +7,8 @@ int main(){ int num_tests = 2; int success = 0; std::vector::iterator it; - std::vector primers = populate_from_file("../data/test.bed"); + int32_t primer_offset = 0; + std::vector primers = populate_from_file("../data/test.bed", primer_offset); std::string primer_names[] = {"WNV_400_1_LEFT", "WNV_400_1_LEFT_alt", "WNV_400_2_LEFT", "WNV_400_1_RIGHT", "WNV_400_2_RIGHT", "WNV_400_3_LEFT", "WNV_400_2_LEFT_alt", "WNV_400_2_RIGHT_alt"}; int primer_indices[] = {0,1,2,3,4,5,6,7,8}; unsigned int primer_start[] = {8,7, 230, 359,658,569,251,352}; diff --git a/tests/test_primer_trim.cpp b/tests/test_primer_trim.cpp index 4bede7cf..02357fcb 100755 --- a/tests/test_primer_trim.cpp +++ b/tests/test_primer_trim.cpp @@ -7,7 +7,8 @@ int main(){ int success = 0; std::string bam = "../data/test.unmapped.sorted.bam"; - std::vector primers = populate_from_file("../data/test.bed"); + int32_t primer_offset = 0; + std::vector primers = populate_from_file("../data/test.bed", primer_offset); int max_primer_len = 0; max_primer_len = get_bigger_primer(primers); std::string region_; diff --git a/tests/test_primer_trim_edge_cases.cpp b/tests/test_primer_trim_edge_cases.cpp index a1da782b..f9f948fa 100755 --- a/tests/test_primer_trim_edge_cases.cpp +++ b/tests/test_primer_trim_edge_cases.cpp @@ -4,7 +4,8 @@ int main(){ int success = 0; std::string bam = "../data/primer_only/primer_edge_cases.bam"; - std::vector primers = populate_from_file("../data/test.bed"); + int32_t primer_offset = 0; + std::vector primers = populate_from_file("../data/test.bed", primer_offset); int max_primer_len = 0; max_primer_len = get_bigger_primer(primers); std::string region_; diff --git a/tests/test_trim.cpp b/tests/test_trim.cpp index e0673557..a222a3cd 100755 --- a/tests/test_trim.cpp +++ b/tests/test_trim.cpp @@ -21,6 +21,7 @@ int test_trim(uint8_t min_qual, uint8_t sliding_window, bool no_write_flag, bool std::string bam = "../data/test.unmapped.sorted.bam"; std::string bed = "../data/test.bed"; std::string pair_info = ""; + int32_t primer_offset = 0; std::string prefix = "/tmp/trim"; std::string bam_out = "/tmp/trim.bam"; @@ -28,7 +29,7 @@ int test_trim(uint8_t min_qual, uint8_t sliding_window, bool no_write_flag, bool std::string cmd = "@PG\tID:ivar-trim\tPN:ivar\tVN:1.0.0\tCL:ivar trim\n"; // Test and check result - res = trim_bam_qual_primer(bam, bed, prefix, region_, min_qual, sliding_window, cmd, no_write_flag, keep_for_reanalysis, min_length, pair_info); + res = trim_bam_qual_primer(bam, bed, prefix, region_, min_qual, sliding_window, cmd, no_write_flag, keep_for_reanalysis, min_length, pair_info, primer_offset); if (res) { success = -1; std::cerr << testname << " failed: trim_bam_qual_primer() returned " << res << std::endl; diff --git a/tests/test_unpaired_trim.cpp b/tests/test_unpaired_trim.cpp index c4451167..5260d92e 100755 --- a/tests/test_unpaired_trim.cpp +++ b/tests/test_unpaired_trim.cpp @@ -7,7 +7,8 @@ int main(){ int success = 0; std::string bam = "../data/test.sim.merged.sorted.bam"; - std::vector primers = populate_from_file("../data/test_merged.bed"); + int32_t primer_offset = 0; + std::vector primers = populate_from_file("../data/test_merged.bed", primer_offset); int max_primer_len = 0; max_primer_len = get_bigger_primer(primers); std::string region_; From 0ff381aa3b2bb4da73b5f045a5f9b7feafa98023 Mon Sep 17 00:00:00 2001 From: Alaa Abdel Latif Date: Thu, 4 Feb 2021 19:26:22 -0800 Subject: [PATCH 2/4] add updates to these files to incorporate additional offset parameter for populate_from_file() --- src/remove_reads_from_amplicon.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/remove_reads_from_amplicon.cpp b/src/remove_reads_from_amplicon.cpp index 8d1863ad..79cd7d04 100644 --- a/src/remove_reads_from_amplicon.cpp +++ b/src/remove_reads_from_amplicon.cpp @@ -1,7 +1,8 @@ #include "remove_reads_from_amplicon.h" int rmv_reads_from_amplicon(std::string bam, std::string region_, std::string bam_out, std::vector amp, std::string bed, std::string cmd){ - std::vector primers = populate_from_file(bed); + int32_t primer_offset = 0; + std::vector primers = populate_from_file(bed, primer_offset); if(primers.size() == 0){ return 0; } From 9b4ee076fb464cb2b72181fd63f76d7aafaac91b Mon Sep 17 00:00:00 2001 From: Alaa Abdel Latif Date: Thu, 4 Feb 2021 19:29:32 -0800 Subject: [PATCH 3/4] add updates to these files to incorporate additional offset parameter for populate_from_file() --- src/get_masked_amplicons.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/get_masked_amplicons.cpp b/src/get_masked_amplicons.cpp index ac20a2bc..f10e6567 100644 --- a/src/get_masked_amplicons.cpp +++ b/src/get_masked_amplicons.cpp @@ -1,7 +1,8 @@ #include "get_masked_amplicons.h" int get_primers_with_mismatches(std::string bed, std::string vpath, std::string out, std::string primer_pair_file){ - std::vector primers = populate_from_file(bed); + int32_t primer_offset = 0; + std::vector primers = populate_from_file(bed, primer_offset); std::vector mismatches_primers; std::vector tmp; if(primers.size() == 0){ From 60e8e6bbde9c7620fa0379de75acfd1ffd38170b Mon Sep 17 00:00:00 2001 From: Alaa Abdel Latif Date: Fri, 5 Feb 2021 09:16:14 -0800 Subject: [PATCH 4/4] overload populate_from_file() --- src/get_masked_amplicons.cpp | 3 +- src/primer_bed.cpp | 69 ++++++++++++++++++++++++++++++ src/primer_bed.h | 1 + src/remove_reads_from_amplicon.cpp | 3 +- tests/test_primer_bed.cpp | 3 +- tests/test_primer_trim.cpp | 3 +- tests/test_unpaired_trim.cpp | 3 +- 7 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/get_masked_amplicons.cpp b/src/get_masked_amplicons.cpp index f10e6567..ac20a2bc 100644 --- a/src/get_masked_amplicons.cpp +++ b/src/get_masked_amplicons.cpp @@ -1,8 +1,7 @@ #include "get_masked_amplicons.h" int get_primers_with_mismatches(std::string bed, std::string vpath, std::string out, std::string primer_pair_file){ - int32_t primer_offset = 0; - std::vector primers = populate_from_file(bed, primer_offset); + std::vector primers = populate_from_file(bed); std::vector mismatches_primers; std::vector tmp; if(primers.size() == 0){ diff --git a/src/primer_bed.cpp b/src/primer_bed.cpp index 4b38f9f6..9fa99867 100644 --- a/src/primer_bed.cpp +++ b/src/primer_bed.cpp @@ -154,6 +154,75 @@ std::vector populate_from_file(std::string path, int32_t offset = 0){ return primers; } +std::vector populate_from_file(std::string path){ + std::ifstream data(path.c_str()); + std::string line; + std::vector primers; + int16_t indice = 0; + while(std::getline(data,line)){ // Remove extra lineStream + std::stringstream lineStream(line); + std::string cell; + int ctr = 0; + primer p; + p.set_strand(0); // Set strand to NULL + while(std::getline(lineStream,cell,'\t')){ + switch(ctr){ + case 0: + p.set_region(cell); + break; + case 1: + if(std::all_of(cell.begin(), cell.end(), ::isdigit)) { + p.set_start(std::stoul(cell)); + } else { + print_bed_format(); + primers.clear(); + return primers; + } + break; + case 2: + if(std::all_of(cell.begin(), cell.end(), ::isdigit)) { + p.set_end(std::stoul(cell) - 1); // Bed format - End is not 0 based + } else { + print_bed_format(); + primers.clear(); + return primers; + } + break; + case 3: + p.set_name(cell); + break; + case 4: + if(std::all_of(cell.begin(), cell.end(), ::isdigit)) { + p.set_score(stoi(cell)); + } else { + print_bed_format(); // score is missing, send warning but continue populating + std::cout << "\nWARNING: The BED file provided did not have the expected score column, but iVar will continue trimming\n" << std::endl; + p.set_score(-1); + } + break; + case 5: + if(cell[0] == '+' || cell[0] == '-') + p.set_strand(cell[0]); + else { + print_bed_format(); + primers.clear(); + return primers; + } + } + ctr++; + } + if(indice == 0 && ctr < 6) + std::cout << "Strand not found in primer BED file so strand will not be considered for trimming" << std::endl; + p.set_indice(indice); + p.set_pair_indice(-1); + p.set_read_count(0); + primers.push_back(p); + indice++; + } + std::cout << "Found " << primers.size() << " primers in BED file" << std::endl; + return primers; +} + std::vector get_primers(std::vector p, unsigned int pos){ std::vector primers_with_mismatches; for(std::vector::iterator it = p.begin(); it != p.end(); ++it) { diff --git a/src/primer_bed.h b/src/primer_bed.h index 4e064085..c8aa71ca 100644 --- a/src/primer_bed.h +++ b/src/primer_bed.h @@ -47,6 +47,7 @@ class primer { }; std::vector populate_from_file(std::string path, int32_t offset); +std::vector populate_from_file(std::string path); std::vector get_primers(std::vector p, unsigned int pos); int get_primer_indice(std::vector p, std::string name); int populate_pair_indices(std::vector &primers, std::string path); diff --git a/src/remove_reads_from_amplicon.cpp b/src/remove_reads_from_amplicon.cpp index 79cd7d04..8d1863ad 100644 --- a/src/remove_reads_from_amplicon.cpp +++ b/src/remove_reads_from_amplicon.cpp @@ -1,8 +1,7 @@ #include "remove_reads_from_amplicon.h" int rmv_reads_from_amplicon(std::string bam, std::string region_, std::string bam_out, std::vector amp, std::string bed, std::string cmd){ - int32_t primer_offset = 0; - std::vector primers = populate_from_file(bed, primer_offset); + std::vector primers = populate_from_file(bed); if(primers.size() == 0){ return 0; } diff --git a/tests/test_primer_bed.cpp b/tests/test_primer_bed.cpp index 9581107a..f395a8e0 100755 --- a/tests/test_primer_bed.cpp +++ b/tests/test_primer_bed.cpp @@ -7,8 +7,7 @@ int main(){ int num_tests = 2; int success = 0; std::vector::iterator it; - int32_t primer_offset = 0; - std::vector primers = populate_from_file("../data/test.bed", primer_offset); + std::vector primers = populate_from_file("../data/test.bed"); std::string primer_names[] = {"WNV_400_1_LEFT", "WNV_400_1_LEFT_alt", "WNV_400_2_LEFT", "WNV_400_1_RIGHT", "WNV_400_2_RIGHT", "WNV_400_3_LEFT", "WNV_400_2_LEFT_alt", "WNV_400_2_RIGHT_alt"}; int primer_indices[] = {0,1,2,3,4,5,6,7,8}; unsigned int primer_start[] = {8,7, 230, 359,658,569,251,352}; diff --git a/tests/test_primer_trim.cpp b/tests/test_primer_trim.cpp index 02357fcb..4bede7cf 100755 --- a/tests/test_primer_trim.cpp +++ b/tests/test_primer_trim.cpp @@ -7,8 +7,7 @@ int main(){ int success = 0; std::string bam = "../data/test.unmapped.sorted.bam"; - int32_t primer_offset = 0; - std::vector primers = populate_from_file("../data/test.bed", primer_offset); + std::vector primers = populate_from_file("../data/test.bed"); int max_primer_len = 0; max_primer_len = get_bigger_primer(primers); std::string region_; diff --git a/tests/test_unpaired_trim.cpp b/tests/test_unpaired_trim.cpp index 5260d92e..c4451167 100755 --- a/tests/test_unpaired_trim.cpp +++ b/tests/test_unpaired_trim.cpp @@ -7,8 +7,7 @@ int main(){ int success = 0; std::string bam = "../data/test.sim.merged.sorted.bam"; - int32_t primer_offset = 0; - std::vector primers = populate_from_file("../data/test_merged.bed", primer_offset); + std::vector primers = populate_from_file("../data/test_merged.bed"); int max_primer_len = 0; max_primer_len = get_bigger_primer(primers); std::string region_;