SeqAn3
sam_tag_dictionary.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <map>
43 #include <variant>
44 
48 #include <seqan3/std/concepts>
49 
50 namespace seqan3::detail
51 {
54  using sam_tag_variant = std::variant<char, int32_t, float, std::string,
55  std::vector<int8_t>, std::vector<uint8_t>,
56  std::vector<int16_t>, std::vector<uint16_t>,
57  std::vector<int32_t>, std::vector<uint32_t>,
58  std::vector<float>>;
59 
61  char constexpr sam_tag_type_char[11] = {'A', 'i', 'f', 'Z', 'B', 'B', 'B', 'B', 'B', 'B', 'B'};
63  char constexpr sam_tag_type_char_extra[11] = {'\0', '\0', '\0', '\0', 'c', 'C', 's', 'S', 'i', 'I', 'f'};
64 }
65 
66 namespace seqan3
67 {
68 
88 template <typename char_t, char_t ...s>
89 constexpr uint16_t operator""_tag()
90 {
91  static_assert(std::Same<char_t, char>, "Illegal SAM tag: Type must be char.");
92  static_assert((sizeof...(s) == 2), "Illegal SAM tag: Exactly two characters must be given.");
93 
94  char constexpr str[sizeof...(s)] = {s...};
95  char constexpr char0 = str[0];
96  char constexpr char1 = str[1];
97 
98  static_assert((is_alpha(char0) && is_alnum(char1)),
99  "Illegal SAM tag: a SAM tag must match /[A-Za-z][A-Za-z0-9]/.");
100 
101  return static_cast<uint16_t>(char0) * 256 + static_cast<uint16_t>(char1);
102 }
103 
180 template <uint16_t tag_value>
182 {
184  using type = detail::sam_tag_variant;
185 };
186 
189 template <uint16_t tag_value>
191 
193 template <> struct sam_tag_type<"AM"_tag> { using type = int32_t; };
194 template <> struct sam_tag_type<"AS"_tag> { using type = int32_t; };
195 template <> struct sam_tag_type<"BC"_tag> { using type = std::string; };
196 template <> struct sam_tag_type<"BQ"_tag> { using type = std::string; };
197 template <> struct sam_tag_type<"BZ"_tag> { using type = std::string; };
198 template <> struct sam_tag_type<"CB"_tag> { using type = std::string; };
199 template <> struct sam_tag_type<"CC"_tag> { using type = std::string; };
200 template <> struct sam_tag_type<"CG"_tag> { using type = std::vector<int32_t>; };
201 template <> struct sam_tag_type<"CM"_tag> { using type = int32_t; };
202 template <> struct sam_tag_type<"CO"_tag> { using type = std::string; };
203 template <> struct sam_tag_type<"CP"_tag> { using type = int32_t; };
204 template <> struct sam_tag_type<"CQ"_tag> { using type = std::string; };
205 template <> struct sam_tag_type<"CR"_tag> { using type = std::string; };
206 template <> struct sam_tag_type<"CS"_tag> { using type = std::string; };
207 template <> struct sam_tag_type<"CT"_tag> { using type = std::string; };
208 template <> struct sam_tag_type<"CY"_tag> { using type = std::string; };
209 template <> struct sam_tag_type<"E2"_tag> { using type = std::string; };
210 template <> struct sam_tag_type<"FI"_tag> { using type = int32_t; };
211 template <> struct sam_tag_type<"FS"_tag> { using type = std::string; };
212 template <> struct sam_tag_type<"FZ"_tag> { using type = std::vector<uint16_t>; };
213 
214 // template <> struct sam_tag_type<"GC"_tag> {};
215 // template <> struct sam_tag_type<"GQ"_tag> {};
216 // template <> struct sam_tag_type<"GS"_tag> {};
217 
218 template <> struct sam_tag_type<"H0"_tag> { using type = int32_t; };
219 template <> struct sam_tag_type<"H1"_tag> { using type = int32_t; };
220 template <> struct sam_tag_type<"H2"_tag> { using type = int32_t; };
221 template <> struct sam_tag_type<"HI"_tag> { using type = int32_t; };
222 template <> struct sam_tag_type<"IH"_tag> { using type = int32_t; };
223 template <> struct sam_tag_type<"LB"_tag> { using type = std::string; };
224 template <> struct sam_tag_type<"MC"_tag> { using type = std::string; };
225 template <> struct sam_tag_type<"MD"_tag> { using type = std::string; };
226 
227 // template <> struct sam_tag_type<"MF"_tag> {};
228 
229 template <> struct sam_tag_type<"MI"_tag> { using type = std::string; };
230 template <> struct sam_tag_type<"MQ"_tag> { using type = int32_t; };
231 template <> struct sam_tag_type<"NH"_tag> { using type = int32_t; };
232 template <> struct sam_tag_type<"NM"_tag> { using type = int32_t; };
233 template <> struct sam_tag_type<"OC"_tag> { using type = std::string; };
234 template <> struct sam_tag_type<"OP"_tag> { using type = int32_t; };
235 template <> struct sam_tag_type<"OQ"_tag> { using type = std::string; };
236 template <> struct sam_tag_type<"OX"_tag> { using type = std::string; };
237 template <> struct sam_tag_type<"PG"_tag> { using type = std::string; };
238 template <> struct sam_tag_type<"PQ"_tag> { using type = int32_t; };
239 template <> struct sam_tag_type<"PT"_tag> { using type = std::string; };
240 template <> struct sam_tag_type<"PU"_tag> { using type = std::string; };
241 template <> struct sam_tag_type<"Q2"_tag> { using type = std::string; };
242 template <> struct sam_tag_type<"QT"_tag> { using type = std::string; };
243 template <> struct sam_tag_type<"QX"_tag> { using type = std::string; };
244 template <> struct sam_tag_type<"R2"_tag> { using type = std::string; };
245 template <> struct sam_tag_type<"RG"_tag> { using type = std::string; };
246 template <> struct sam_tag_type<"RT"_tag> { using type = std::string; };
247 template <> struct sam_tag_type<"RX"_tag> { using type = std::string; };
248 
249 // template <> struct sam_tag_type<"S2"_tag> {};
250 
251 template <> struct sam_tag_type<"SA"_tag> { using type = std::string; };
252 template <> struct sam_tag_type<"SM"_tag> { using type = int32_t; };
253 
254 // template <> struct sam_tag_type<"SQ"_tag> {};
255 
256 template <> struct sam_tag_type<"TC"_tag> { using type = int32_t; };
257 template <> struct sam_tag_type<"U2"_tag> { using type = std::string; };
258 template <> struct sam_tag_type<"UQ"_tag> { using type = int32_t; };
260 
339 class sam_tag_dictionary : public std::map<uint16_t, detail::sam_tag_variant>
340 {
341 private:
343  using base_type = std::map<uint16_t, detail::sam_tag_variant>;
344 
345 public:
347  using variant_type = detail::sam_tag_variant;
348 
364  template <uint16_t tag>
369  auto & get() &
370  {
371  if ((*this).count(tag) == 0)
372  (*this)[tag] = sam_tag_type_t<tag>{}; // set correct type if tag is not set yet on
373 
374  return std::get<sam_tag_type_t<tag>>((*this)[tag]);
375  }
376 
378  template <uint16_t tag>
382  auto && get() &&
383  {
384  if ((*this).count(tag) == 0)
385  (*this)[tag] = sam_tag_type_t<tag>{}; // set correct type if tag is not set yet on
386 
387  return std::get<sam_tag_type_t<tag>>(std::move((*this)[tag]));
388  }
389 
392  template <uint16_t tag>
396  auto const & get() const &
397  {
398  return std::get<sam_tag_type_t<tag>>((*this).at(tag));
399  }
400 
403  template <uint16_t tag>
407  auto const && get() const &&
408  {
409  return std::get<sam_tag_type_t<tag>>(std::move((*this).at(tag)));
410  }
412 };
413 
414 } // namespace seqan3
Provides concepts for core language types and relations that don&#39;t have concepts in C++20 (yet)...
auto constexpr is_alnum
Checks whether c is a alphanumeric character.
Definition: parse_condition.hpp:245
typename sam_tag_type< tag_value >::type sam_tag_type_t
Short cut helper for seqan3::sam_tag_type::type.
Definition: sam_tag_dictionary.hpp:190
Provides seqan3::type_list and auxiliary metafunctions.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
detail::sam_tag_variant variant_type
The variant type defining all valid SAM tag field types.
Definition: sam_tag_dictionary.hpp:347
auto constexpr is_alpha
Checks whether c is a alphabetical character.
Definition: parse_condition.hpp:264
The Concepts library.
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
detail::sam_tag_variant type
The type for all unknown tags with no extra overload defaults to an std::variant. ...
Definition: sam_tag_dictionary.hpp:184
Definition: aligned_sequence_concept.hpp:288
Provides parse conditions for tokenization.
The generic base class.
Definition: sam_tag_dictionary.hpp:181
The SAM tag dictionary class that stores all optional SAM fields.
Definition: sam_tag_dictionary.hpp:339