@@ -313,6 +313,11 @@ struct mod_prob_buffer {
313313 bam_parse_basemod (aln.b , m.get ());
314314 // ADS: or bam_parse_basemod2(aln.b, m, HTS_MOD_REPORT_UNCHECKED)
315315
316+ int n_types{};
317+ const auto types = bam_mods_recorded (m.get (), &n_types);
318+ if (n_types < 2 || (types[h_idx] != ' h' && types[m_idx] != ' m' ))
319+ return false ;
320+
316321 int pos{};
317322 int n{};
318323 while ((n = bam_next_basemod (aln.b , m.get (), d, max_mods, &pos)) > 0 ) {
@@ -502,7 +507,7 @@ struct mod_prob_stats {
502507
503508 mod_prob_stats () : m{hts_base_mod_state_alloc (), &hts_base_mod_state_free} {};
504509
505- [[nodiscard]] auto
510+ auto
506511 operator ()(const bamxx::bam_rec &aln) {
507512 static constexpr auto h_idx = 0 ;
508513 static constexpr auto m_idx = 1 ;
@@ -514,6 +519,11 @@ struct mod_prob_stats {
514519 bam_parse_basemod (aln.b , m.get ());
515520 // ADS: or bam_parse_basemod2(aln.b, m, HTS_MOD_REPORT_UNCHECKED)
516521
522+ int n_types{};
523+ const auto types = bam_mods_recorded (m.get (), &n_types);
524+ if (n_types < 2 || (types[h_idx] != ' h' && types[m_idx] != ' m' ))
525+ return ;
526+
517527 int pos{};
518528 int n{};
519529 while ((n = bam_next_basemod (aln.b , m.get (), d, max_mods, &pos)) > 0 ) {
@@ -907,7 +917,8 @@ struct read_processor {
907917
908918[[nodiscard]] static auto
909919valid_modification_types (const std::string &infile,
910- const std::uint32_t n_reads_to_check) -> bool {
920+ const std::uint32_t n_reads_to_check)
921+ -> std::pair<bool, std::string> {
911922 using mstate = hts_base_mod_state;
912923 std::unique_ptr<mstate, void (*)(mstate *)> m (hts_base_mod_state_alloc (),
913924 &hts_base_mod_state_free);
@@ -918,6 +929,8 @@ valid_modification_types(const std::string &infile,
918929 if (!hdr)
919930 throw std::runtime_error (" failed to read header" );
920931
932+ std::string message;
933+
921934 std::uint32_t read_count{};
922935 bool valid_types{true };
923936 bamxx::bam_rec aln;
@@ -929,9 +942,17 @@ valid_modification_types(const std::string &infile,
929942 // ADS: or bam_parse_basemod2(aln.b, m, HTS_MOD_REPORT_UNCHECKED)
930943 int n_types{};
931944 const auto types = bam_mods_recorded (m.get (), &n_types);
932- valid_types = n_types >= 2 && types[0 ] == ' h' && types[1 ] == ' m' ;
945+ valid_types = (n_types == 1 && types[0 ] == ' C' ) ||
946+ (n_types >= 2 && types[0 ] == ' h' && types[1 ] == ' m' );
947+ if (!valid_types) {
948+ message = " n_types: " + std::to_string (n_types) + " \n " ;
949+ for (auto i = 0 ; i < n_types; ++i) {
950+ message += " type[" + std::to_string (i) +
951+ " ]=" + std::to_string (static_cast <char >(types[i])) + " \n " ;
952+ }
953+ }
933954 }
934- return valid_types;
955+ return std::make_pair ( valid_types, message) ;
935956}
936957
937958[[nodiscard]] static auto
@@ -1053,9 +1074,11 @@ main_nanocount(int argc, char *argv[]) { // NOLINT(*-avoid-c-arrays)
10531074 std::ostringstream cmd;
10541075 std::copy (argv, argv + argc, std::ostream_iterator<const char *>(cmd, " " ));
10551076
1056- if (!valid_modification_types (mapped_reads_file, n_reads_to_check)) {
1057- std::cerr << " modification types are not valid\n "
1058- << " expected h=0 and m=1\n " ;
1077+ const auto [is_valid, message] =
1078+ valid_modification_types (mapped_reads_file, n_reads_to_check);
1079+ if (!is_valid) {
1080+ std::cerr << " modification types are not valid. Violation:\n "
1081+ << message << ' \n ' ;
10591082 return EXIT_FAILURE;
10601083 }
10611084
0 commit comments