Skip to content

Commit

Permalink
Don't allow custom SVTYPES
Browse files Browse the repository at this point in the history
Also, minor fixes related to ALT ID and the BND type
  • Loading branch information
jmmut committed Dec 5, 2018
1 parent 54ccb71 commit 0a54b59
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 22 deletions.
2 changes: 1 addition & 1 deletion inc/util/stream_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ namespace ebi
* This is a generic method that prints a collection if it has the operations ".begin()" and ".end()"
* defined and they provide iterators, and the inner type has an overloaded "operator<<"
*
* provides the default open/close/separator tags to print collections like this: [2,4]
* provides the default open/close/separator tags to print collections like this: [2, 4]
*/
template <typename T>
std::ostream &print_container(std::ostream &os, const T &container) {
Expand Down
18 changes: 16 additions & 2 deletions inc/vcf/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,18 @@ namespace ebi
ErrorFix error_fix = ErrorFix::IRRECOVERABLE_VALUE,
const std::string &value = "",
const std::string &expected_value = "")
: Error{line, message}, error_fix{error_fix}, value{value}, expected_value{expected_value} {
: MetaSectionError{line, message, "", error_fix, value, expected_value} { }

MetaSectionError(size_t line,
const std::string &message,
const std::string &detailed_message,
ErrorFix error_fix = ErrorFix::IRRECOVERABLE_VALUE,
const std::string &value = "",
const std::string &expected_value = "")
: Error{line, message, detailed_message},
error_fix{error_fix},
value{value},
expected_value{expected_value} {
if (error_fix == ErrorFix::RECOVERABLE_VALUE && (value.empty() || expected_value.empty())) {
throw std::invalid_argument("An error with recoverable meta defintion must provide non-empty field and expected values");
}
Expand Down Expand Up @@ -290,7 +301,10 @@ namespace ebi
ErrorFix error_fix = ErrorFix::IRRECOVERABLE_VALUE,
const std::string &field = "",
const std::string &expected_value = "")
: BodySectionError{line, message}, error_fix{error_fix}, field{field}, expected_value{expected_value} {
: BodySectionError{line, message, detailed_message},
error_fix{error_fix},
field{field},
expected_value{expected_value} {
if (error_fix == ErrorFix::RECOVERABLE_VALUE && expected_value.empty()) {
throw std::invalid_argument{"The program had an internal error: An error with recoverable value must provide a non-empty expected value"};
}
Expand Down
10 changes: 10 additions & 0 deletions inc/vcf/file_structure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <vector>

#include <boost/variant.hpp>
#include <set>

#include "util/stream_utils.hpp"
#include "vcf/error.hpp"
Expand Down Expand Up @@ -205,6 +206,15 @@ namespace ebi
{ PS, { INTEGER, "1" } }
};

const std::set<std::string> PREDEFINED_INFO_SVTYPES{
DEL,
INS,
DUP,
INV,
CNV,
BND,
};

inline std::string const &get_predefined_type(
std::map<std::string, std::pair<std::string, std::string>>::const_iterator const &predefined_tag)
{
Expand Down
15 changes: 7 additions & 8 deletions src/vcf/meta_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,17 @@ namespace ebi

void MetaEntryVisitor::check_alt_id(std::string const & id_field) const
{
// Check ID main type (prefix before ':') is "DEL" | "INS" | "DUP" | "INV" | "CNV"
// Check ID main type (prefix before ':') is one of the predefined ones
auto main_type_position_end = id_field.find(':');
bool colon_present = main_type_position_end != std::string::npos;
if (colon_present) {
auto main_type = id_field.substr(0, main_type_position_end);
if (main_type != DEL
&& main_type != INS
&& main_type != DUP
&& main_type != INV
&& main_type != CNV
&& main_type != BND) {
throw new MetaSectionError{entry.line, "ALT metadata ID does not begin with DEL/INS/DUP/INV/CNV"};
if (!ebi::util::contains(PREDEFINED_INFO_SVTYPES, main_type)) {
std::stringstream message;
message << "ALT metadata ID containing type and subtype (separated by colon) should have as "
"first level type one of: ";
ebi::util::print_container(message, PREDEFINED_INFO_SVTYPES, "", ", ", "");
throw new MetaSectionError{entry.line, message.str(), "Found ID was '" + id_field + "'"};
}
}
}
Expand Down
23 changes: 14 additions & 9 deletions src/vcf/record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <iostream>

#include "util/algo_utils.hpp"
#include "util/stream_utils.hpp"
#include "util/logger.hpp"
#include "vcf/file_structure.hpp"
#include "vcf/record.hpp"
Expand Down Expand Up @@ -201,15 +202,12 @@ namespace ebi
bool colon_present = main_type_position_end != std::string::npos;
if (colon_present) {
auto main_type = alt_id.substr(0, main_type_position_end);
if (main_type != DEL
&& main_type != INS
&& main_type != DUP
&& main_type != INV
&& main_type != CNV
&& main_type != BND) {
throw new AlternateAllelesBodyError{line,
"Alternate ID is not prefixed by DEL/INS/DUP/INV/CNV and "
"suffixed by ':' and a text sequence"};
if (!ebi::util::contains(PREDEFINED_INFO_SVTYPES, main_type)) {
std::stringstream message;
message << "ALT ID containing type and subtype (separated by colon) should have as "
"first level type one of: ";
ebi::util::print_container(message, PREDEFINED_INFO_SVTYPES, "", ", ", "");
throw new AlternateAllelesBodyError{line, message.str(), "Found ID was '" + alt_id + "'"};
}
}
}
Expand Down Expand Up @@ -433,6 +431,13 @@ namespace ebi
}
}
}
} else if (field_key == SVTYPE) {
if (!ebi::util::contains(PREDEFINED_INFO_SVTYPES, field_value)) {
std::stringstream message;
message << "INFO " << SVTYPE << " must be one of: ";
ebi::util::print_container(message, PREDEFINED_INFO_SVTYPES, "", ", ", "");
throw new InfoBodyError{line, message.str(), "Found " + SVTYPE + " was '" + field_value + "'"};
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/vcf/vcf.ragel
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@

action meta_alt_id_err {
ErrorPolicy::handle_error(*this, new MetaSectionError{n_lines,
"ALT metadata ID is not prefixed by DEL/INS/DUP/INV/CNV and suffixed by ':' and a text sequence"});
"ALT metadata ID is not prefixed by DEL/INS/DUP/INV/CNV/BND and suffixed by ':' and a text sequence"});
fhold; fgoto meta_section_skip;
}

Expand Down Expand Up @@ -514,7 +514,7 @@
record_alt_snv = bases ;

## Indel alternates can be represented by standardized prefixes or an asterisk
record_alt_prefix = '<DEL>' | '<INS>' | '<DUP>' | '<INV>' | '<CNV>' | '<DUP:TANDEM>' | '<DEL:ME:' (alnum)+ '>' | '<INS:ME:' (alnum)+ '>';
record_alt_prefix = '<DEL>' | '<INS>' | '<DUP>' | '<INV>' | '<CNV>' | '<BND>' | '<DUP:TANDEM>' | '<DEL:ME:' (alnum)+ '>' | '<INS:ME:' (alnum)+ '>';
record_alt_indel = record_alt_prefix | '*';

## Other alternates can be any identifier surrounded by < > symbols
Expand Down
14 changes: 14 additions & 0 deletions test/vcf/predefined_info_tags_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,20 @@ namespace ebi
{ "0|1" },
source}),
vcf::InfoBodyError*);
CHECK_THROWS_AS( (vcf::Record{
1,
"chr1",
123456,
{ "id123" },
"A",
{ "AT" },
1.0,
{ vcf::PASS },
{ {vcf::SVTYPE, "UNK"} },
{ vcf::GT },
{ "0|1" },
source}),
vcf::InfoBodyError*);

CHECK_THROWS_AS( (vcf::Record{
1,
Expand Down

0 comments on commit 0a54b59

Please sign in to comment.