SeqAn3
detail.hpp
Go to the documentation of this file.
1 
2 // ============================================================================
3 // SeqAn - The Library for Sequence Analysis
4 // ============================================================================
5 //
6 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
7 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // * Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 // * Redistributions in binary form must reproduce the above copyright
16 // notice, this list of conditions and the following disclaimer in the
17 // documentation and/or other materials provided with the distribution.
18 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
19 // its contributors may be used to endorse or promote products derived
20 // from this software without specific prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
26 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 // DAMAGE.
33 //
34 // ============================================================================
35 
41 #pragma once
42 
43 #include <sstream>
44 
47 #include <seqan3/std/concepts>
48 #include <seqan3/std/ranges>
49 
50 #include <range/v3/view/zip.hpp>
51 
52 namespace seqan3::detail
53 {
97 template<typename reference_char_type, typename query_char_type>
99  requires std::detail::WeaklyEqualityComparableWith<reference_char_type, gap> &&
100  std::detail::WeaklyEqualityComparableWith<query_char_type, gap>
102 char compare_aligned_values(reference_char_type const reference_char,
103  query_char_type const query_char,
104  bool const extended_cigar)
105 {
106  return (reference_char == gap::GAP)
107  ? (query_char == gap::GAP)
108  ? 'P'
109  : 'I'
110  : (query_char == gap::GAP)
111  ? 'D'
112  : (extended_cigar)
113  ? (query_char == reference_char)
114  ? '='
115  : 'X'
116  : 'M';
117 }
118 
150 template<std::ranges::ForwardRange ref_seq_type, std::ranges::ForwardRange query_seq_type>
152  requires std::detail::WeaklyEqualityComparableWith<gap, reference_t<ref_seq_type>> &&
153  std::detail::WeaklyEqualityComparableWith<gap, reference_t<query_seq_type>>
155 std::string get_cigar_string(ref_seq_type && ref_seq,
156  query_seq_type && query_seq,
157  uint32_t const query_start_pos = 0,
158  uint32_t const query_end_pos = 0,
159  bool const extended_cigar = false)
160 {
161  if (ref_seq.size() != query_seq.size())
162  throw std::logic_error("The aligned sequences must have the same length.");
163 
164  std::ostringstream result;
165 
166  if (!ref_seq.size())
167  return std::string(); // return empty string if sequences are empty
168 
169  // Add (S)oft-clipping at the start of the read
170  if (query_start_pos)
171  result << query_start_pos << 'S';
172 
173  // Create cigar string from alignment
174  // -------------------------------------------------------------------------
175  // initialize first operation:
176  char tmp_char{compare_aligned_values(ref_seq[0], query_seq[0], extended_cigar)};
177  unsigned tmp_length{0};
178 
179  // go through alignment columns
180  for (auto column : ranges::view::zip(ref_seq, query_seq))
181  {
182  char next_op = compare_aligned_values(std::get<0>(column), std::get<1>(column), extended_cigar);
183 
184  if (tmp_char == next_op)
185  {
186  ++tmp_length;
187  }
188  else
189  {
190  result << tmp_length << tmp_char;
191  tmp_char = next_op;
192  tmp_length = 1;
193  }
194  }
195  // append last cigar element
196  result << tmp_length << tmp_char;
197 
198  // Add (S)oft-clipping at the end of the read
199  if (query_end_pos)
200  result << query_end_pos << 'S';
201 
202  return result.str();
203 }
204 
245 template<tuple_like_concept alignment_type>
247  requires std::tuple_size_v<remove_cvref_t<alignment_type>> == 2
249 std::string get_cigar_string(alignment_type && alignment,
250  uint32_t const query_start_pos = 0,
251  uint32_t const query_end_pos = 0,
252  bool const extended_cigar = false)
253 {
254  return get_cigar_string(get<0>(alignment), get<1>(alignment),
255  query_start_pos, query_end_pos, extended_cigar);
256 }
257 
258 } // namespace seqan3::detail
Includes the aligned_sequence_concept and the related insert_gap and erase_gap functions to enable st...
Provides seqan3::tuple_like_concept.
The Concepts library.
Adaptations of concepts from the Ranges TS.
Definition: aligned_sequence_concept.hpp:288