inline static LibraryFormat formatFromID(uint8_t id) { ReadType rt; ReadOrientation ro; ReadStrandedness rs; switch (id & 0x01) { case 0: rt = ReadType::SINGLE_END; break; case 1: rt = ReadType::PAIRED_END; break; } switch ((id >> 1) & 0xB) { case static_cast<uint8_t>(ReadOrientation::SAME): ro = ReadOrientation::SAME; break; case static_cast<uint8_t>(ReadOrientation::AWAY): ro = ReadOrientation::AWAY; break; case static_cast<uint8_t>(ReadOrientation::TOWARD): ro = ReadOrientation::TOWARD; break; case static_cast<uint8_t>(ReadOrientation::NONE): ro = ReadOrientation::NONE; break; } switch ((id >> 3) & 0x6F) { case static_cast<uint8_t>(ReadStrandedness::SA): rs = ReadStrandedness::SA; break; case static_cast<uint8_t>(ReadStrandedness::AS): rs = ReadStrandedness::AS; break; case static_cast<uint8_t>(ReadStrandedness::S): rs = ReadStrandedness::S; break; case static_cast<uint8_t>(ReadStrandedness::A): rs = ReadStrandedness::A; break; case static_cast<uint8_t>(ReadStrandedness::U): rs = ReadStrandedness::U; break; } return LibraryFormat(rt, ro, rs); }
// Determine the library type of paired-end reads LibraryFormat hitType(int32_t end1Start, bool end1Fwd, uint32_t len1, int32_t end2Start, bool end2Fwd, uint32_t len2, bool canDovetail) { // If the reads come from opposite strands if (end1Fwd != end2Fwd) { // and if read 1 comes from the forward strand if (end1Fwd) { // then if read 1 start < read 2 start ==> ISF // NOTE: We can't really delineate between inward facing reads that stretch // past each other and outward facing reads --- the purpose of stretch is to help // make this determinateion. int32_t stretch = canDovetail ? len2 : 0; if (end1Start <= end2Start + stretch) { return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::TOWARD, ReadStrandedness::SA); } // otherwise read 2 start < read 1 start ==> OSF else { return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::AWAY, ReadStrandedness::SA); } } // and if read 2 comes from the forward strand if (end2Fwd) { // then if read 2 start <= read 1 start ==> ISR // NOTE: We can't really delineate between inward facing reads that stretch // past each other and outward facing reads --- the purpose of stretch is to help // make this determinateion. int32_t stretch = canDovetail ? len1 : 0; if (end2Start <= end1Start + stretch) { return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::TOWARD, ReadStrandedness::AS); } // otherwise, read 2 start > read 1 start ==> OSR else { return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::AWAY, ReadStrandedness::AS); } } } else { // Otherwise, the reads come from the same strand if (end1Fwd) { // if it's the forward strand ==> MSF return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::SAME, ReadStrandedness::S); } else { // if it's the reverse strand ==> MSR return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::SAME, ReadStrandedness::A); } } // SHOULD NOT GET HERE spdlog::get("jointLog")->error("ERROR: Could not associate any known library type with read! " "Please report this bug!\n"); std::this_thread::sleep_for(std::chrono::seconds(1)); std::exit(-1); return LibraryFormat(ReadType::PAIRED_END, ReadOrientation::NONE, ReadStrandedness::U); }
SCENARIO("Library types are encoded/decoded properly") { GIVEN("A collection of library formats") { std::unordered_map<std::string, LibraryFormat> fm = {{"U", LibraryFormat(ReadType::SINGLE_END, ReadOrientation::NONE, ReadStrandedness::U)}, {"SF", LibraryFormat(ReadType::SINGLE_END, ReadOrientation::NONE, ReadStrandedness::S)}, {"SR", LibraryFormat(ReadType::SINGLE_END, ReadOrientation::NONE, ReadStrandedness::A)}, {"IU", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::TOWARD, ReadStrandedness::U)}, {"ISF", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::TOWARD, ReadStrandedness::S)}, {"ISR", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::TOWARD, ReadStrandedness::A)}, {"OU", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::AWAY, ReadStrandedness::U)}, {"OSF", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::AWAY, ReadStrandedness::S)}, {"OSR", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::AWAY, ReadStrandedness::A)}, {"MU", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::SAME, ReadStrandedness::U)}, {"MSF", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::SAME, ReadStrandedness::S)}, {"MSR", LibraryFormat(ReadType::PAIRED_END, ReadOrientation::SAME, ReadStrandedness::A)}}; for (auto& kv : fm) { WHEN("type is " + kv.first) { uint8_t id = kv.second.formatID(); THEN("decodes as " + kv.first) { REQUIRE(kv.second == LibraryFormat::formatFromID(id)); } } } } } SCENARIO("Paired-end library types have proper compatibility") {