85 template <
typename stream_type,
86 typename seq_legal_alph_type,
87 typename ref_seqs_type,
88 typename ref_ids_type,
92 typename ref_seq_type,
94 typename ref_offset_type,
101 typename tag_dict_type,
102 typename e_value_type,
103 typename bit_score_type>
106 ref_seqs_type & ref_seqs,
111 offset_type & offset,
112 ref_seq_type & SEQAN3_DOXYGEN_ONLY(ref_seq),
113 ref_id_type & ref_id,
114 ref_offset_type & ref_offset,
116 cigar_type & cigar_vector,
120 tag_dict_type & tag_dict,
121 e_value_type & SEQAN3_DOXYGEN_ONLY(e_value),
122 bit_score_type & SEQAN3_DOXYGEN_ONLY(bit_score));
124 template <
typename stream_type,
125 typename header_type,
128 typename ref_seq_type,
129 typename ref_id_type,
134 typename tag_dict_type>
137 [[maybe_unused]] header_type && header,
138 [[maybe_unused]] seq_type && seq,
139 [[maybe_unused]] qual_type && qual,
140 [[maybe_unused]] id_type &&
id,
141 [[maybe_unused]] int32_t
const offset,
142 [[maybe_unused]] ref_seq_type && SEQAN3_DOXYGEN_ONLY(ref_seq),
143 [[maybe_unused]] ref_id_type && ref_id,
145 [[maybe_unused]] align_type && align,
146 [[maybe_unused]] cigar_type && cigar_vector,
147 [[maybe_unused]]
sam_flag const flag,
148 [[maybe_unused]] uint8_t
const mapq,
149 [[maybe_unused]] mate_type && mate,
150 [[maybe_unused]] tag_dict_type && tag_dict,
151 [[maybe_unused]]
double SEQAN3_DOXYGEN_ONLY(e_value),
152 [[maybe_unused]]
double SEQAN3_DOXYGEN_ONLY(bit_score));
188 ret[
static_cast<index_t
>(
'I')] = 1;
189 ret[
static_cast<index_t
>(
'D')] = 2;
190 ret[
static_cast<index_t
>(
'N')] = 3;
191 ret[
static_cast<index_t
>(
'S')] = 4;
192 ret[
static_cast<index_t
>(
'H')] = 5;
193 ret[
static_cast<index_t
>(
'P')] = 6;
194 ret[
static_cast<index_t
>(
'=')] = 7;
195 ret[
static_cast<index_t
>(
'X')] = 8;
202 static uint16_t
reg2bin(int32_t beg, int32_t end) noexcept
205 if (beg >> 14 == end >> 14)
return ((1 << 15) - 1) / 7 + (beg >> 14);
206 if (beg >> 17 == end >> 17)
return ((1 << 12) - 1) / 7 + (beg >> 17);
207 if (beg >> 20 == end >> 20)
return ((1 << 9) - 1) / 7 + (beg >> 20);
208 if (beg >> 23 == end >> 23)
return ((1 << 6) - 1) / 7 + (beg >> 23);
209 if (beg >> 26 == end >> 26)
return ((1 << 3) - 1) / 7 + (beg >> 26);
213 using format_sam_base::read_field;
221 template <
typename stream_view_type, std::
integral number_type>
222 void read_field(stream_view_type && stream_view, number_type & target)
224 std::ranges::copy_n(std::ranges::begin(stream_view),
sizeof(target),
reinterpret_cast<char *
>(&target));
232 template <
typename stream_view_type>
233 void read_field(stream_view_type && stream_view,
float & target)
235 std::ranges::copy_n(std::ranges::begin(stream_view),
sizeof(int32_t),
reinterpret_cast<char *
>(&target));
248 template <
typename stream_view_type,
typename optional_value_type>
251 optional_value_type tmp;
252 read_field(std::forward<stream_view_type>(stream_view), tmp);
256 template <
typename stream_view_type,
typename value_type>
258 stream_view_type && stream_view,
259 value_type const & SEQAN3_DOXYGEN_ONLY(value));
261 template <
typename stream_view_type>
264 template <
typename cigar_input_type>
271 template <
typename stream_type,
272 typename seq_legal_alph_type,
273 typename ref_seqs_type,
274 typename ref_ids_type,
277 typename offset_type,
278 typename ref_seq_type,
279 typename ref_id_type,
280 typename ref_offset_type,
287 typename tag_dict_type,
288 typename e_value_type,
289 typename bit_score_type>
292 ref_seqs_type & ref_seqs,
297 offset_type & offset,
298 ref_seq_type & SEQAN3_DOXYGEN_ONLY(ref_seq),
299 ref_id_type & ref_id,
300 ref_offset_type & ref_offset,
302 cigar_type & cigar_vector,
306 tag_dict_type & tag_dict,
307 e_value_type & SEQAN3_DOXYGEN_ONLY(e_value),
308 bit_score_type & SEQAN3_DOXYGEN_ONLY(bit_score))
310 static_assert(detail::decays_to_ignore_v<ref_offset_type> ||
311 detail::is_type_specialisation_of_v<ref_offset_type, std::optional>,
312 "The ref_offset must be a specialisation of std::optional.");
314 static_assert(detail::decays_to_ignore_v<mapq_type> || std::same_as<mapq_type, uint8_t>,
315 "The type of field::mapq must be uint8_t.");
317 static_assert(detail::decays_to_ignore_v<flag_type> || std::same_as<flag_type, sam_flag>,
318 "The type of field::flag must be seqan3::sam_flag.");
323 [[maybe_unused]] int32_t offset_tmp{};
324 [[maybe_unused]] int32_t soft_clipping_end{};
326 [[maybe_unused]] int32_t ref_length{0}, seq_length{0};
348 for (int32_t ref_idx = 0; ref_idx < n_ref; ++ref_idx)
353 std::ranges::copy_n(std::ranges::begin(stream_view), l_name - 1,
string_buffer.
data());
354 std::ranges::next(std::ranges::begin(stream_view));
358 if constexpr (detail::decays_to_ignore_v<ref_seqs_type>)
363 auto & reference_ids = header.
ref_ids();
369 header.
ref_dict.emplace(reference_ids.back(), reference_ids.size() - 1);
380 "' found in BAM file header (header.ref_ids():",
383 else if (id_it->second != ref_idx)
386 " does not correspond to the position ", id_it->second,
387 " in the header (header.ref_ids():", header.
ref_ids(),
").")};
389 else if (std::get<0>(header.
ref_id_info[id_it->second]) != l_ref)
391 throw format_error{
"Provided reference has unequal length as specified in the header."};
397 if (std::ranges::begin(stream_view) == std::ranges::end(stream_view))
406 if (core.
refID >=
static_cast<int32_t
>(header.
ref_ids().size()) || core.
refID < -1)
409 "header.ref_ids(), which has size ", header.
ref_ids().size(),
".")};
411 else if (core.
refID > -1)
422 if constexpr (!detail::decays_to_ignore_v<mate_type>)
436 std::ranges::next(std::ranges::begin(stream_view));
440 if constexpr (!detail::decays_to_ignore_v<align_type> || !detail::decays_to_ignore_v<cigar_type>)
457 auto seq_stream = stream_view
465 if constexpr (detail::decays_to_ignore_v<seq_type>)
467 auto skip_sequence_bytes = [&] ()
471 std::ranges::next(std::ranges::begin(stream_view));
474 if constexpr (!detail::decays_to_ignore_v<align_type>)
477 "If you want to read ALIGNMENT but not SEQ, the alignment"
478 " object must store a sequence container at the second (query) position.");
480 if (!tmp_cigar_vector.empty())
482 assert(core.
l_seq == (seq_length + offset_tmp + soft_clipping_end));
483 using alph_t = std::ranges::range_value_t<decltype(get<1>(align))>;
484 constexpr
auto from_dna16 = detail::convert_through_char_representation<alph_t, dna16sam>;
486 get<1>(align).reserve(seq_length);
488 auto tmp_iter = std::ranges::begin(seq_stream);
489 std::ranges::advance(tmp_iter, offset_tmp / 2);
493 get<1>(align).push_back(from_dna16[
to_rank(get<1>(*tmp_iter))]);
498 for (
size_t i = (seq_length / 2); i > 0; --i)
500 get<1>(align).push_back(from_dna16[
to_rank(get<0>(*tmp_iter))]);
501 get<1>(align).push_back(from_dna16[
to_rank(get<1>(*tmp_iter))]);
507 get<1>(align).push_back(from_dna16[
to_rank(get<0>(*tmp_iter))]);
512 std::ranges::advance(tmp_iter, (soft_clipping_end + !(seq_length & 1)) / 2);
516 skip_sequence_bytes();
522 skip_sequence_bytes();
527 using alph_t = std::ranges::range_value_t<decltype(
seq)>;
528 constexpr
auto from_dna16 = detail::convert_through_char_representation<alph_t, dna16sam>;
530 for (
auto [d1, d2] : seq_stream)
540 std::ranges::next(std::ranges::begin(stream_view));
543 if constexpr (!detail::decays_to_ignore_v<align_type>)
545 assign_unaligned(get<1>(align),
546 seq |
views::slice(
static_cast<std::ranges::range_difference_t<seq_type>
>(offset_tmp),
547 std::ranges::distance(
seq) - soft_clipping_end));
561 assert(remaining_bytes >= 0);
564 while (tags_view.size() > 0)
569 if constexpr (!detail::decays_to_ignore_v<align_type> || !detail::decays_to_ignore_v<cigar_type>)
574 if (core.
l_seq != 0 && offset_tmp == core.
l_seq)
576 if constexpr (detail::decays_to_ignore_v<tag_dict_type> | detail::decays_to_ignore_v<seq_type>)
579 "N' suggests that the cigar string exceeded 65535 elements and was therefore ",
580 "stored in the optional field CG. You need to read in the field::tags and "
581 "field::seq in order to access this information.")};
585 auto it = tag_dict.
find(
"CG"_tag);
587 if (it == tag_dict.end())
589 "N' suggests that the cigar string exceeded 65535 elements and was therefore ",
590 "stored in the optional field CG but this tag is not present in the given ",
593 auto cigar_view = std::views::all(std::get<std::string>(it->second));
595 offset_tmp = soft_clipping_end = 0;
599 if constexpr (!detail::decays_to_ignore_v<align_type>)
601 assign_unaligned(get<1>(align),
602 seq |
views::slice(
static_cast<std::ranges::range_difference_t<seq_type>
>(offset_tmp),
603 std::ranges::distance(
seq) - soft_clipping_end));
610 if constexpr (!detail::decays_to_ignore_v<align_type>)
613 if constexpr (!detail::decays_to_ignore_v<cigar_type>)
614 std::swap(cigar_vector, tmp_cigar_vector);
618 template <
typename stream_type,
619 typename header_type,
622 typename ref_seq_type,
623 typename ref_id_type,
628 typename tag_dict_type>
631 [[maybe_unused]] header_type && header,
632 [[maybe_unused]] seq_type && seq,
633 [[maybe_unused]] qual_type && qual,
634 [[maybe_unused]] id_type &&
id,
635 [[maybe_unused]] int32_t
const offset,
636 [[maybe_unused]] ref_seq_type && SEQAN3_DOXYGEN_ONLY(ref_seq),
637 [[maybe_unused]] ref_id_type && ref_id,
639 [[maybe_unused]] align_type && align,
640 [[maybe_unused]] cigar_type && cigar_vector,
641 [[maybe_unused]]
sam_flag const flag,
642 [[maybe_unused]] uint8_t
const mapq,
643 [[maybe_unused]] mate_type && mate,
644 [[maybe_unused]] tag_dict_type && tag_dict,
645 [[maybe_unused]]
double SEQAN3_DOXYGEN_ONLY(e_value),
646 [[maybe_unused]]
double SEQAN3_DOXYGEN_ONLY(bit_score))
651 static_assert((std::ranges::forward_range<seq_type> &&
652 alphabet<std::ranges::range_reference_t<seq_type>>),
653 "The seq object must be a std::ranges::forward_range over "
654 "letters that model seqan3::alphabet.");
656 static_assert((std::ranges::forward_range<id_type> &&
657 alphabet<std::ranges::range_reference_t<id_type>>),
658 "The id object must be a std::ranges::forward_range over "
659 "letters that model seqan3::alphabet.");
661 static_assert((std::ranges::forward_range<ref_seq_type> &&
662 alphabet<std::ranges::range_reference_t<ref_seq_type>>),
663 "The ref_seq object must be a std::ranges::forward_range "
664 "over letters that model seqan3::alphabet.");
666 if constexpr (!detail::decays_to_ignore_v<ref_id_type>)
668 static_assert((std::ranges::forward_range<ref_id_type> ||
671 "The ref_id object must be a std::ranges::forward_range "
672 "over letters that model seqan3::alphabet or an integral or a std::optional<integral>.");
676 "The align object must be a std::pair of two ranges whose "
677 "value_type is comparable to seqan3::gap");
680 std::equality_comparable_with<
gap, std::ranges::range_reference_t<decltype(std::get<0>(align))>> &&
681 std::equality_comparable_with<
gap, std::ranges::range_reference_t<decltype(std::get<1>(align))>>),
682 "The align object must be a std::pair of two ranges whose "
683 "value_type is comparable to seqan3::gap");
685 static_assert((std::ranges::forward_range<qual_type> &&
686 alphabet<std::ranges::range_reference_t<qual_type>>),
687 "The qual object must be a std::ranges::forward_range "
688 "over letters that model seqan3::alphabet.");
691 "The mate object must be a std::tuple of size 3 with "
692 "1) a std::ranges::forward_range with a value_type modelling seqan3::alphabet, "
693 "2) a std::integral or std::optional<std::integral>, and "
694 "3) a std::integral.");
696 static_assert(((std::ranges::forward_range<decltype(std::get<0>(
mate))> ||
702 "The mate object must be a std::tuple of size 3 with "
703 "1) a std::ranges::forward_range with a value_type modelling seqan3::alphabet, "
704 "2) a std::integral or std::optional<std::integral>, and "
705 "3) a std::integral.");
708 "The tag_dict object must be of type seqan3::sam_tag_dictionary.");
710 if constexpr (detail::decays_to_ignore_v<header_type>)
712 throw format_error{
"BAM can only be written with a header but you did not provide enough information! "
713 "You can either construct the output file with ref_ids and ref_seqs information and "
714 "the header will be created for you, or you can access the `header` member directly."};
735 int32_t l_text{
static_cast<int32_t
>(os.
str().size())};
736 std::ranges::copy_n(
reinterpret_cast<char *
>(&l_text), 4, stream_it);
740 int32_t n_ref{
static_cast<int32_t
>(header.
ref_ids().size())};
741 std::ranges::copy_n(
reinterpret_cast<char *
>(&n_ref), 4, stream_it);
743 for (int32_t ridx = 0; ridx < n_ref; ++ridx)
745 int32_t l_name{
static_cast<int32_t
>(header.
ref_ids()[ridx].size()) + 1};
746 std::ranges::copy_n(
reinterpret_cast<char *
>(&l_name), 4, stream_it);
748 std::ranges::copy(header.
ref_ids()[ridx].begin(), header.
ref_ids()[ridx].end(), stream_it);
751 std::ranges::copy_n(
reinterpret_cast<char *
>(&get<0>(header.
ref_id_info[ridx])), 4, stream_it);
760 int32_t ref_length{};
764 if (!std::ranges::empty(cigar_vector))
766 int32_t dummy_seq_length{};
767 for (
auto & [
count, operation] : cigar_vector)
770 else if (!std::ranges::empty(get<0>(align)) && !std::ranges::empty(get<1>(align)))
772 ref_length = std::ranges::distance(get<1>(align));
778 int32_t off_end{
static_cast<int32_t
>(std::ranges::distance(
seq)) -
offset};
780 for (
auto chr : get<1>(align))
784 off_end -= ref_length;
788 if (cigar_vector.size() >= (1 << 16))
791 cigar_vector.resize(2);
792 cigar_vector[0] =
cigar{
static_cast<uint32_t
>(std::ranges::distance(
seq)),
'S'_cigar_operation};
793 cigar_vector[1] =
cigar{
static_cast<uint32_t
>(std::ranges::distance(get<1>(align))),
'N'_cigar_operation};
803 uint8_t read_name_size = std::min<uint8_t>(std::ranges::distance(
id), 254) + 1;
804 read_name_size +=
static_cast<uint8_t
>(read_name_size == 1);
814 static_cast<uint16_t
>(cigar_vector.size()),
816 static_cast<int32_t
>(std::ranges::distance(
seq)),
818 get<1>(
mate).value_or(-1),
822 auto check_and_assign_id_to = [&header] ([[maybe_unused]]
auto & id_source,
823 [[maybe_unused]]
auto & id_target)
827 if constexpr (!detail::decays_to_ignore_v<id_t>)
829 if constexpr (std::integral<id_t>)
831 id_target = id_source;
833 else if constexpr (detail::is_type_specialisation_of_v<id_t, std::optional>)
835 id_target = id_source.value_or(-1);
839 if (!std::ranges::empty(id_source))
843 if constexpr (std::ranges::contiguous_range<decltype(id_source)> &&
844 std::ranges::sized_range<decltype(id_source)> &&
845 std::ranges::borrowed_range<decltype(id_source)>)
855 "The ref_id type is not convertible to the reference id information stored in the "
856 "reference dictionary of the header object.");
858 id_it = header.
ref_dict.find(id_source);
864 "not be found in BAM header ref_dict: ",
868 id_target = id_it->second;
875 check_and_assign_id_to(
ref_id, core.refID);
878 check_and_assign_id_to(get<0>(
mate), core.next_refID);
881 core.block_size =
sizeof(core) - 4 +
883 core.n_cigar_op * 4 +
884 (core.l_seq + 1) / 2 +
886 tag_dict_binary_str.
size();
888 std::ranges::copy_n(
reinterpret_cast<char *
>(&core),
sizeof(core), stream_it);
890 if (std::ranges::empty(
id))
893 std::ranges::copy_n(std::ranges::begin(
id), core.l_read_name - 1, stream_it);
897 for (
auto [cigar_count, op] : cigar_vector)
899 cigar_count = cigar_count << 4;
901 std::ranges::copy_n(
reinterpret_cast<char *
>(&cigar_count), 4, stream_it);
905 using alph_t = std::ranges::range_value_t<seq_type>;
906 constexpr
auto to_dna16 = detail::convert_through_char_representation<dna16sam, alph_t>;
908 auto sit = std::ranges::begin(
seq);
909 for (int32_t sidx = 0; sidx < ((core.l_seq & 1) ? core.l_seq - 1 : core.l_seq); ++sidx, ++sit)
914 stream_it =
static_cast<char>(compressed_chr);
918 stream_it =
static_cast<char>(
to_rank(to_dna16[
to_rank(*sit)]) << 4);
921 if (std::ranges::empty(
qual))
924 std::ranges::copy_n(v.begin(), core.l_seq, stream_it);
928 if (std::ranges::distance(
qual) != core.l_seq)
930 core.l_seq,
". Got quality with size ",
931 std::ranges::distance(
qual),
" instead.")};
934 std::ranges::copy_n(v.begin(), core.l_seq, stream_it);
938 stream << tag_dict_binary_str;
943 template <
typename stream_view_type,
typename value_type>
945 stream_view_type && stream_view,
946 value_type const & SEQAN3_DOXYGEN_ONLY(value))
980 template <
typename stream_view_type>
989 auto it = std::ranges::begin(stream_view);
990 uint16_t tag =
static_cast<uint16_t
>(*it) << 8;
993 tag +=
static_cast<uint16_t
>(*it);
1012 target[tag] =
static_cast<int32_t
>(tmp);
1019 target[tag] =
static_cast<int32_t
>(tmp);
1026 target[tag] =
static_cast<int32_t
>(tmp);
1033 target[tag] =
static_cast<int32_t
>(tmp);
1047 target[tag] =
static_cast<int32_t
>(tmp);
1060 while (!is_char<'\0'>(*it))
1073 while (!is_char<'\0'>(*it))
1080 throw format_error{
"Hexadecimal tag has an uneven number of digits!"};
1088 target[tag] = byte_array;
1093 char array_value_type_id = *it;
1096 switch (array_value_type_id)
1121 "must be one of [cCsSiIf] but '", array_value_type_id,
"' was given.")};
1127 "SAM tag must be one of [A,i,Z,H,B,f] but '", type_id,
"' was given.")};
1145 template <
typename cigar_input_type>
1149 char operation{
'\0'};
1151 int32_t ref_length{}, seq_length{};
1152 uint32_t operation_and_count{};
1153 constexpr
char const * cigar_mapping =
"MIDNSHP=X*******";
1154 constexpr uint32_t cigar_mask = 0x0f;
1156 if (n_cigar_op == 0)
1157 return std::tuple{operations, ref_length, seq_length};
1161 while (n_cigar_op > 0)
1163 std::ranges::copy_n(std::ranges::begin(cigar_input),
1164 sizeof(operation_and_count),
1165 reinterpret_cast<char*
>(&operation_and_count));
1166 operation = cigar_mapping[operation_and_count & cigar_mask];
1167 count = operation_and_count >> 4;
1174 return std::tuple{operations, ref_length, seq_length};
1184 auto stream_variant_fn = [&result] (
auto && arg)
1189 if constexpr (std::same_as<T, int32_t>)
1192 size_t const absolute_arg = std::abs(arg);
1194 bool const negative = arg < 0;
1195 n = n * n + 2 * negative;
1201 result[result.size() - 1] =
'C';
1202 result.append(
reinterpret_cast<char const *
>(&arg), 1);
1207 result[result.size() - 1] =
'S';
1208 result.append(
reinterpret_cast<char const *
>(&arg), 2);
1213 result[result.size() - 1] =
'c';
1214 int8_t tmp =
static_cast<int8_t
>(arg);
1215 result.append(
reinterpret_cast<char const *
>(&tmp), 1);
1220 result[result.size() - 1] =
's';
1221 int16_t tmp =
static_cast<int16_t
>(arg);
1222 result.append(
reinterpret_cast<char const *
>(&tmp), 2);
1227 result.append(
reinterpret_cast<char const *
>(&arg), 4);
1232 else if constexpr (std::same_as<T, std::string>)
1234 result.append(
reinterpret_cast<char const *
>(arg.data()), arg.size() + 1);
1236 else if constexpr (!std::ranges::range<T>)
1238 result.append(
reinterpret_cast<char const *
>(&arg),
sizeof(arg));
1242 int32_t sz{
static_cast<int32_t
>(arg.size())};
1243 result.append(
reinterpret_cast<char *
>(&sz), 4);
1244 result.append(
reinterpret_cast<char const *
>(arg.data()),
1245 arg.size() *
sizeof(std::ranges::range_value_t<T>));
1249 for (
auto & [tag, variant] : tag_dict)
1251 result.push_back(
static_cast<char>(tag / 256));
1252 result.push_back(
static_cast<char>(tag % 256));
Provides seqan3::detail::convert_through_char_representation.
Provides the C++20 <bit> header if it is not already available.
constexpr derived_type & assign_char(char_type const chr) noexcept
Assign from a character, implicitly converts invalid characters.
Definition: alphabet_base.hpp:211
constexpr derived_type & assign_rank(rank_type const c) noexcept
Assign from a numeric value.
Definition: alphabet_base.hpp:264
The seqan3::cigar semialphabet pairs a counter with a seqan3::cigar::operation letter.
Definition: cigar.hpp:59
Functionally the same as std::ostreambuf_iterator, but offers writing a range more efficiently.
Definition: fast_ostreambuf_iterator.hpp:39
A 16 letter DNA alphabet, containing all IUPAC symbols minus the gap and plus an equality sign ('=').
Definition: dna16sam.hpp:48
The actual implementation of seqan3::cigar::operation for documentation purposes only.
Definition: cigar_operation.hpp:48
The alphabet of a gap character '-'.
Definition: gap.hpp:39
The SAM tag dictionary class that stores all optional SAM fields.
Definition: sam_tag_dictionary.hpp:326
Provides various transformation traits used by the range module.
Auxiliary for pretty printing of exception messages.
Provides seqan3::debug_stream and related types.
Provides type traits for working with templates.
Provides seqan3::dna16sam.
T emplace_back(T... args)
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
Provides seqan3::detail::fast_ostreambuf_iterator.
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
constexpr T bit_ceil(T x) noexcept
Calculates the smallest integral power of two that is not smaller than x.
Definition: bit:133
constexpr int countr_zero(T x) noexcept
Returns the number of consecutive 0 bits in the value of x, starting from the least significant bit (...
Definition: bit:199
sam_flag
An enum flag that describes the properties of an aligned read (given as a SAM record).
Definition: sam_flag.hpp:73
std::vector< cigar > get_cigar_vector(alignment_type &&alignment, uint32_t const query_start_pos=0, uint32_t const query_end_pos=0, bool const extended_cigar=false)
Creates a cigar string (SAM format) given a seqan3::detail::pairwise_alignment represented by two seq...
Definition: cigar.hpp:201
std::string get_cigar_string(std::vector< cigar > const &cigar_vector)
Transforms a vector of cigar elements into a string representation.
Definition: cigar.hpp:263
@ flag
The alignment flag (bit information), uint16_t value.
@ ref_offset
Sequence (seqan3::field::ref_seq) relative start position (0-based), unsigned value.
@ mapq
The mapping quality of the seqan3::field::seq alignment, usually a Phred-scaled score.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
@ mate
The mate pair information given as a std::tuple of reference name, offset and template length.
@ ref_id
The identifier of the (reference) sequence that seqan3::field::seq was aligned to.
@ seq
The "sequence", usually a range of nucleotides or amino acids.
@ qual
The qualities, usually in Phred score notation.
constexpr void consume(rng_t &&rng)
Iterate over a range (consumes single-pass input ranges).
Definition: misc.hpp:28
decltype(detail::transform< trait_t >(list_t{})) transform
Apply a transformation trait to every type in the list and return a seqan3::type_list of the results.
Definition: traits.hpp:434
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: traits.hpp:168
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:150
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:145
constexpr auto istreambuf
A view factory that returns a view over the stream buffer of an input stream.
Definition: istreambuf.hpp:114
constexpr auto take_exactly_or_throw
A view adaptor that returns the first size elements from the underlying range and also exposes size i...
Definition: take_exactly.hpp:91
constexpr auto repeat_n
A view factory that repeats a given value n times.
Definition: repeat_n.hpp:94
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:70
Provides seqan3::detail::ignore_output_iterator for writing to null stream.
The generic alphabet concept that covers most data types used in ranges.
Resolves to std::ranges::implicitly_convertible_to<type1, type2>(). <dl class="no-api">This entity i...
A more refined container concept than seqan3::container.
Whether a type behaves like a tuple.
Provides various utility functions.
Auxiliary functions for the alignment IO.
Provides seqan3::views::istreambuf.
std::tuple< std::vector< cigar >, int32_t, int32_t > parse_cigar(cigar_input_type &&cigar_input)
Parses a cigar string into a vector of operation-count pairs (e.g. (M, 3)).
Definition: cigar.hpp:134
constexpr char sam_tag_type_char_extra[12]
Each types SAM tag type extra char id. Index corresponds to the seqan3::detail::sam_tag_variant types...
Definition: sam_tag_dictionary.hpp:38
void update_alignment_lengths(int32_t &ref_length, int32_t &seq_length, char const cigar_operation, uint32_t const cigar_count)
Updates the sequence lengths by cigar_count depending on the cigar operation op.
Definition: cigar.hpp:105
constexpr char sam_tag_type_char[12]
Each SAM tag type char identifier. Index corresponds to the seqan3::detail::sam_tag_variant types.
Definition: sam_tag_dictionary.hpp:36
std::string to_string(value_type &&...values)
Streams all parameters via the seqan3::debug_stream and returns a concatenated string.
Definition: to_string.hpp:29
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
Provides various utility functions.
Adaptations of concepts from the Ranges TS.
Provides seqan3::sam_file_output_options.
Provides the seqan3::sam_tag_dictionary class and auxiliaries.
Provides helper data structures for the seqan3::sam_file_output.
Provides seqan3::views::slice.
The options type defines various option members that influence the behavior of all or some formats.
Definition: output_options.hpp:23
Exposes the value_type of another type.
Definition: pre.hpp:58
Provides seqan3::views::take_exactly and seqan3::views::take_exactly_or_throw.
Provides seqan3::views::take_until and seqan3::views::take_until_or_throw.
Provides character predicates for tokenisation.
Provides seqan3::tuple_like.