Loading CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ list(APPEND CMAKE_CXX_FLAGS "-std=c++11") set(CPACK_PACKAGE_VERSION_MAJOR 1) set(CPACK_PACKAGE_VERSION_MINOR 92) set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_VERSION_PATCH 3) set(CPACK_GENERATOR TGZ) set(CPACK_SOURCE_GENERATOR TGZ) set(CPACK_SOURCE_IGNORE_FILES ${CPACK_SOURCE_IGNORE_FILES} ".kdev4" "~" "build" "nbproject" "test_data" "CMakeLists.txt.user*") Loading Changes.md +18 −0 Original line number Diff line number Diff line Changes ======= 1.92.3 ====== - htio2 library Fixed bugs on missing move constructor of Option class, and now it works properly with GCC 4.7. 1.92.2 ====== - Refined unit test for ht2-overlap. - htio2 library Fixed a bug on command-line option parser, where values with leading "-" was recognized as option key. 1.92.1 ====== Loading src/htio2/OptionParser.cpp +49 −24 Original line number Diff line number Diff line Loading @@ -101,8 +101,21 @@ string Option::BoolSwitch::to_string() return ""; } Option::Option(Option &&other) noexcept : name_long(other.name_long) , name_short(other.name_short) , group(other.group) , store(other.store) , flags(other.flags) , option_desc(other.option_desc) , value_desc(other.value_desc) { other.store = nullptr; } Option::~Option() { if (store) delete store; } Loading Loading @@ -262,22 +275,31 @@ void OptionParser::parse_options(int& argc, char** argv) { // long key in "--xxx" style if (curr_token[1] == '-') { Option* next_option = find_option_long(curr_token); if (next_option) { // clear previous values _dump_value_group_(values_by_option, curr_option, curr_value_group); // find option object curr_option = find_option_long(curr_token); curr_option = next_option; } else { curr_value_group.emplace_back(i, curr_token); } } // short key in "-x" style else { Option* next_option = find_option_short(curr_token[1]); if (next_option) { // clear previous values _dump_value_group_(values_by_option, curr_option, curr_value_group); // find option object curr_option = find_option_short(curr_token[1]); curr_option = next_option; // short key contains a value if (curr_token.length() > 2) Loading @@ -292,7 +314,12 @@ void OptionParser::parse_options(int& argc, char** argv) exit(EXIT_FAILURE); } curr_value_group.push_back(make_pair(i, curr_token_value)); curr_value_group.emplace_back(i, curr_token_value); } } else { curr_value_group.emplace_back(i, curr_token); } } } Loading Loading @@ -515,8 +542,7 @@ Option* OptionParser::find_option_long(const string &key) if (matched_keys.size() == 0) { fprintf(stderr, "ERROR: unknown option \"%s\"\n", key.c_str()); exit(EXIT_FAILURE); return nullptr; } else if (matched_keys.size() == 1) { Loading @@ -538,8 +564,7 @@ Option* OptionParser::find_option_short(char key) return options[it->second]; else { fprintf(stderr, "ERROR: unknown option \"-%c\"\n", key); exit(EXIT_FAILURE); return nullptr; } } Loading src/htio2/OptionParser.h +6 −4 Original line number Diff line number Diff line Loading @@ -180,11 +180,13 @@ public: { } virtual ~Option(); Option(Option&& other) noexcept; // copying is not allowed Option(const Option& other) = delete; Option& operator = (const Option& other) = delete; private: Option(const Option& other); Option& operator = (const Option& other); virtual ~Option(); protected: static bool validate_name(char name); Loading t/t_ht_overlap.cpp +118 −3 Original line number Diff line number Diff line #include "TestFramework.h" #include "TestConfig.h" #include "htio2/FastqIO.h" #include "htio2/PairedEndIO.h" #include "htio2/FastqSeq.h" #include <map> using namespace std; using namespace htio2; using namespace htio2::juce; void parse_fields(const string& desc, map<string, int>& result) { StringArray tokens; tokens.addTokens(String(desc), " =", ""); if (tokens.size() % 2) { fprintf(stderr, "invalid token size %d, not even\n", tokens.size()); abort(); } for (int i = 0; i < tokens.size(); i+=2) { const String& key = tokens[i]; const String& value = tokens[i+1]; result[key.toStdString()] = value.getIntValue(); } } void TestFramework::content() { const char* cmd = "../src/ht2-overlap -q -i " TEST_SOURCE_DIR "/test1.fastq.gz " TEST_SOURCE_DIR "/test2.fastq.gz -o ovlp -u novlp"; ok(!system(cmd), cmd); OK(text_file_eq("ovlp.fastq.gz", TEST_SOURCE_DIR "/test_ovlp.fastq.gz")); OK(text_file_eq("novlp_1.fastq.gz", TEST_SOURCE_DIR "/test_novlp_1.fastq.gz")); OK(text_file_eq("novlp_2.fastq.gz", TEST_SOURCE_DIR "/test_novlp_2.fastq.gz")); map<string,string> ovlp_seqs; map<string,int> offsets; { htio2::FastqIO fh_ovlp("ovlp.fastq.gz", htio2::READ); htio2::FastqSeq seq; while (fh_ovlp.next_seq(seq)) { map<string,int> attrs; parse_fields(seq.desc, attrs); if (!attrs.count("kmer_pos_a")) { fprintf(stderr, "no attribute kmer_pos_a\n"); abort(); } if (!attrs.count("kmer_pos_b")) { fprintf(stderr, "no attribute kmer_pos_b\n"); abort(); } ovlp_seqs[seq.id] = seq.seq; offsets[seq.id] = attrs["kmer_pos_b"] - attrs["kmer_pos_a"]; } } { htio2::FastqSeq seq1; htio2::FastqSeq seq2; htio2::PairedEndIO fh_in(TEST_SOURCE_DIR "/test1.fastq.gz", TEST_SOURCE_DIR "/test2.fastq.gz", htio2::READ); while (fh_in.next_pair(seq1,seq2)) { if (seq1.id != seq2.id) { fprintf(stderr, "conflict ID: %s and %s\n", seq1.id.c_str(), seq2.id.c_str()); abort(); } if (!ovlp_seqs.count(seq1.id)) continue; const string& merged_seq = ovlp_seqs[seq1.id]; int offset = offsets[seq1.id]; for (int i = 0; i < merged_seq.length(); i++) { int i1 = numeric_limits<int>::max(); int i2 = numeric_limits<int>::max(); if (offset >= 0) { i1 = i - offset; i2 = i; } else { i1 = i; i2 = i + offset; } if (0 <= i1 && i1 < seq1.length()) { if (0 <= i2 && i2 < seq2.length()) { if (seq1.quality[i1] >= seq2.quality[i2]) IS(seq1.seq[i1], merged_seq[i]); else IS(seq2.seq[i2], merged_seq[i]); } else { IS(seq1.seq[i1], merged_seq[i]); } } else { if (0 <= i2 && i2 < seq2.length()) { IS(seq2.seq[i2], merged_seq[i]); } else { fprintf(stderr, "invalid position %d and %d at %d", i1, i2, i); abort(); } } } } } } Loading
CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ list(APPEND CMAKE_CXX_FLAGS "-std=c++11") set(CPACK_PACKAGE_VERSION_MAJOR 1) set(CPACK_PACKAGE_VERSION_MINOR 92) set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_VERSION_PATCH 3) set(CPACK_GENERATOR TGZ) set(CPACK_SOURCE_GENERATOR TGZ) set(CPACK_SOURCE_IGNORE_FILES ${CPACK_SOURCE_IGNORE_FILES} ".kdev4" "~" "build" "nbproject" "test_data" "CMakeLists.txt.user*") Loading
Changes.md +18 −0 Original line number Diff line number Diff line Changes ======= 1.92.3 ====== - htio2 library Fixed bugs on missing move constructor of Option class, and now it works properly with GCC 4.7. 1.92.2 ====== - Refined unit test for ht2-overlap. - htio2 library Fixed a bug on command-line option parser, where values with leading "-" was recognized as option key. 1.92.1 ====== Loading
src/htio2/OptionParser.cpp +49 −24 Original line number Diff line number Diff line Loading @@ -101,8 +101,21 @@ string Option::BoolSwitch::to_string() return ""; } Option::Option(Option &&other) noexcept : name_long(other.name_long) , name_short(other.name_short) , group(other.group) , store(other.store) , flags(other.flags) , option_desc(other.option_desc) , value_desc(other.value_desc) { other.store = nullptr; } Option::~Option() { if (store) delete store; } Loading Loading @@ -262,22 +275,31 @@ void OptionParser::parse_options(int& argc, char** argv) { // long key in "--xxx" style if (curr_token[1] == '-') { Option* next_option = find_option_long(curr_token); if (next_option) { // clear previous values _dump_value_group_(values_by_option, curr_option, curr_value_group); // find option object curr_option = find_option_long(curr_token); curr_option = next_option; } else { curr_value_group.emplace_back(i, curr_token); } } // short key in "-x" style else { Option* next_option = find_option_short(curr_token[1]); if (next_option) { // clear previous values _dump_value_group_(values_by_option, curr_option, curr_value_group); // find option object curr_option = find_option_short(curr_token[1]); curr_option = next_option; // short key contains a value if (curr_token.length() > 2) Loading @@ -292,7 +314,12 @@ void OptionParser::parse_options(int& argc, char** argv) exit(EXIT_FAILURE); } curr_value_group.push_back(make_pair(i, curr_token_value)); curr_value_group.emplace_back(i, curr_token_value); } } else { curr_value_group.emplace_back(i, curr_token); } } } Loading Loading @@ -515,8 +542,7 @@ Option* OptionParser::find_option_long(const string &key) if (matched_keys.size() == 0) { fprintf(stderr, "ERROR: unknown option \"%s\"\n", key.c_str()); exit(EXIT_FAILURE); return nullptr; } else if (matched_keys.size() == 1) { Loading @@ -538,8 +564,7 @@ Option* OptionParser::find_option_short(char key) return options[it->second]; else { fprintf(stderr, "ERROR: unknown option \"-%c\"\n", key); exit(EXIT_FAILURE); return nullptr; } } Loading
src/htio2/OptionParser.h +6 −4 Original line number Diff line number Diff line Loading @@ -180,11 +180,13 @@ public: { } virtual ~Option(); Option(Option&& other) noexcept; // copying is not allowed Option(const Option& other) = delete; Option& operator = (const Option& other) = delete; private: Option(const Option& other); Option& operator = (const Option& other); virtual ~Option(); protected: static bool validate_name(char name); Loading
t/t_ht_overlap.cpp +118 −3 Original line number Diff line number Diff line #include "TestFramework.h" #include "TestConfig.h" #include "htio2/FastqIO.h" #include "htio2/PairedEndIO.h" #include "htio2/FastqSeq.h" #include <map> using namespace std; using namespace htio2; using namespace htio2::juce; void parse_fields(const string& desc, map<string, int>& result) { StringArray tokens; tokens.addTokens(String(desc), " =", ""); if (tokens.size() % 2) { fprintf(stderr, "invalid token size %d, not even\n", tokens.size()); abort(); } for (int i = 0; i < tokens.size(); i+=2) { const String& key = tokens[i]; const String& value = tokens[i+1]; result[key.toStdString()] = value.getIntValue(); } } void TestFramework::content() { const char* cmd = "../src/ht2-overlap -q -i " TEST_SOURCE_DIR "/test1.fastq.gz " TEST_SOURCE_DIR "/test2.fastq.gz -o ovlp -u novlp"; ok(!system(cmd), cmd); OK(text_file_eq("ovlp.fastq.gz", TEST_SOURCE_DIR "/test_ovlp.fastq.gz")); OK(text_file_eq("novlp_1.fastq.gz", TEST_SOURCE_DIR "/test_novlp_1.fastq.gz")); OK(text_file_eq("novlp_2.fastq.gz", TEST_SOURCE_DIR "/test_novlp_2.fastq.gz")); map<string,string> ovlp_seqs; map<string,int> offsets; { htio2::FastqIO fh_ovlp("ovlp.fastq.gz", htio2::READ); htio2::FastqSeq seq; while (fh_ovlp.next_seq(seq)) { map<string,int> attrs; parse_fields(seq.desc, attrs); if (!attrs.count("kmer_pos_a")) { fprintf(stderr, "no attribute kmer_pos_a\n"); abort(); } if (!attrs.count("kmer_pos_b")) { fprintf(stderr, "no attribute kmer_pos_b\n"); abort(); } ovlp_seqs[seq.id] = seq.seq; offsets[seq.id] = attrs["kmer_pos_b"] - attrs["kmer_pos_a"]; } } { htio2::FastqSeq seq1; htio2::FastqSeq seq2; htio2::PairedEndIO fh_in(TEST_SOURCE_DIR "/test1.fastq.gz", TEST_SOURCE_DIR "/test2.fastq.gz", htio2::READ); while (fh_in.next_pair(seq1,seq2)) { if (seq1.id != seq2.id) { fprintf(stderr, "conflict ID: %s and %s\n", seq1.id.c_str(), seq2.id.c_str()); abort(); } if (!ovlp_seqs.count(seq1.id)) continue; const string& merged_seq = ovlp_seqs[seq1.id]; int offset = offsets[seq1.id]; for (int i = 0; i < merged_seq.length(); i++) { int i1 = numeric_limits<int>::max(); int i2 = numeric_limits<int>::max(); if (offset >= 0) { i1 = i - offset; i2 = i; } else { i1 = i; i2 = i + offset; } if (0 <= i1 && i1 < seq1.length()) { if (0 <= i2 && i2 < seq2.length()) { if (seq1.quality[i1] >= seq2.quality[i2]) IS(seq1.seq[i1], merged_seq[i]); else IS(seq2.seq[i2], merged_seq[i]); } else { IS(seq1.seq[i1], merged_seq[i]); } } else { if (0 <= i2 && i2 < seq2.length()) { IS(seq2.seq[i2], merged_seq[i]); } else { fprintf(stderr, "invalid position %d and %d at %d", i1, i2, i); abort(); } } } } } }