101 class sequence_file_input_format<format_fasta>
105 using format_tag = format_fasta;
110 sequence_file_input_format() noexcept = default;
111 sequence_file_input_format(sequence_file_input_format const &) = delete;
114 sequence_file_input_format & operator=(sequence_file_input_format const &) = delete;
115 sequence_file_input_format(sequence_file_input_format &&) noexcept = default;
116 sequence_file_input_format & operator=(sequence_file_input_format &&) noexcept = default;
117 ~sequence_file_input_format() noexcept = default;
121 template <typename stream_type,
122 typename seq_legal_alph_type,
bool seq_qual_combined,
126 void read(stream_type & stream,
127 sequence_file_input_options<seq_legal_alph_type, seq_qual_combined> const & options,
130 qual_type & SEQAN3_DOXYGEN_ONLY(qualities))
135 read_id(stream_view, options,
id);
138 read_seq(stream_view, options, sequence);
144 template <
typename stream_view_t,
145 typename seq_legal_alph_type,
bool seq_qual_combined,
147 void read_id(stream_view_t & stream_view,
148 sequence_file_input_options<seq_legal_alph_type, seq_qual_combined>
const & options,
151 auto const is_id = is_char<'>
'> || is_char<';
'>; 153 if (!is_id(*begin(stream_view))) 154 throw parse_error{std::string{"Expected to be on beginning of ID, but "} + is_id.msg.str() + 155 " evaluated to false on " + detail::make_printable(*begin(stream_view))}; 158 if constexpr (!detail::decays_to_ignore_v<id_type>) 160 if (options.truncate_ids) 162 #if SEQAN3_WORKAROUND_VIEW_PERFORMANCE 163 auto it = stream_view.begin(); 164 auto e = stream_view.end(); 165 for (; (it != e) && (is_id || is_blank)(*it); ++it) 168 bool at_delimiter = false; 169 for (; it != e; ++it) 171 if ((is_cntrl || is_blank)(*it)) 176 id.push_back(assign_char_to(*it, value_type_t<id_type>{})); 180 throw unexpected_end_of_input{"FastA ID line did not end in newline."}; 182 for (; (it != e) && ((!is_char<'\n
'>)(*it)); ++it) 185 #else // ↑↑↑ WORKAROUND | ORIGINAL ↓↓↓ 187 std::ranges::copy(stream_view | std::view::drop_while(is_id || is_blank) // skip leading > 188 | view::take_until_or_throw(is_cntrl || is_blank) // read ID until delimiter… 189 | view::char_to<value_type_t<id_type>>, 190 std::back_inserter(id)); // … ^A is old delimiter 192 // consume rest of line 193 detail::consume(stream_view | view::take_line_or_throw); 194 #endif // SEQAN3_WORKAROUND_VIEW_PERFORMANCE 199 #if SEQAN3_WORKAROUND_VIEW_PERFORMANCE 200 auto it = stream_view.begin(); 201 auto e = stream_view.end(); 202 for (; (it != e) && (is_id || is_blank)(*it); ++it) 205 bool at_delimiter = false; 206 for (; it != e; ++it) 208 if ((is_char<'\n
'>)(*it)) 213 id.push_back(assign_char_to(*it, value_type_t<id_type>{})); 217 throw unexpected_end_of_input{"FastA ID line did not end in newline."}; 219 #else // ↑↑↑ WORKAROUND | ORIGINAL ↓↓↓ 221 std::ranges::copy(stream_view | view::take_line_or_throw // read line 222 | std::view::drop_while(is_id || is_blank) // skip leading > 223 | view::char_to<value_type_t<id_type>>, 224 std::back_inserter(id)); 225 #endif // SEQAN3_WORKAROUND_VIEW_PERFORMANCE 230 detail::consume(stream_view | view::take_line_or_throw); 235 template <typename stream_view_t, 236 typename seq_legal_alph_type, bool seq_qual_combined, 238 void read_seq(stream_view_t & stream_view, 239 sequence_file_input_options<seq_legal_alph_type, seq_qual_combined> const &, 242 auto constexpr is_id = is_char<'>
'> || is_char<';
'>; 244 if constexpr (!detail::decays_to_ignore_v<seq_type>) 246 auto constexpr not_in_alph = !is_in_alphabet<seq_legal_alph_type>; 248 #if SEQAN3_WORKAROUND_VIEW_PERFORMANCE 249 auto it = stream_view.begin(); 250 auto e = stream_view.end(); 251 for (; (it != e) && ((!is_id)(*it)); ++it) 253 if ((is_space || is_digit)(*it)) 255 else if (not_in_alph(*it)) 257 throw parse_error{std::string{"Encountered an unexpected letter: "} + 258 not_in_alph.msg.str() + 259 " evaluated to true on " + 260 detail::make_printable(*it)}; 263 seq.push_back(assign_char_to(*it, value_type_t<seq_type>{})); 266 #else // ↑↑↑ WORKAROUND | ORIGINAL ↓↓↓ 268 std::ranges::copy(stream_view | view::take_until(is_id) // until next header (or end) 269 | std::view::filter(!(is_space || is_digit))// ignore whitespace and numbers 270 | std::view::transform([not_in_alph] (char const c) 274 throw parse_error{std::string{"Encountered an unexpected letter: "} + 275 not_in_alph.msg.str() + 276 " evaluated to false on " + 277 detail::make_printable(c)}; 280 }) // enforce legal alphabet 281 | view::char_to<value_type_t<seq_type>>, // convert to actual target alphabet 282 std::back_inserter(seq)); 283 #endif // SEQAN3_WORKAROUND_VIEW_PERFORMANCE 287 detail::consume(stream_view | view::take_until(is_id)); 295 class sequence_file_output_format<format_fasta> 299 using format_tag = format_fasta; 304 sequence_file_output_format() noexcept = default; //!< Defaulted. 306 sequence_file_output_format(sequence_file_output_format const &) = delete; 308 sequence_file_output_format & operator=(sequence_file_output_format const &) = delete; 309 sequence_file_output_format(sequence_file_output_format &&) noexcept = default; //!< Defaulted. 310 sequence_file_output_format & operator=(sequence_file_output_format &&) noexcept = default; //!< Defaulted. 311 ~sequence_file_output_format() noexcept = default; //!< Defaulted. 315 template <typename stream_type, // constraints checked by file 316 typename seq_type, // other constraints checked inside function 319 void write(stream_type & stream, 320 sequence_file_output_options const & options, 321 seq_type && sequence, 323 qual_type && SEQAN3_DOXYGEN_ONLY(qualities)) 326 seqan3::ostreambuf_iterator stream_it{stream}; 329 if constexpr (detail::decays_to_ignore_v<id_type>) 331 throw std::logic_error{"The ID field may not be set to ignore when writing FASTA files."}; 335 if (empty(id)) //[[unlikely]] 336 throw std::runtime_error{"The ID field may not be empty when writing FASTA files."}; 338 write_id(stream_it, options, id); 342 if constexpr (detail::decays_to_ignore_v<seq_type>) // sequence 344 throw std::logic_error{"The SEQ and SEQ_QUAL fields may not both be set to ignore when writing FASTA files."}; 348 if (empty(sequence)) //[[unlikely]] 349 throw std::runtime_error{"The SEQ field may not be empty when writing FASTA files."}; 351 write_seq(stream_it, options, sequence); 356 template <typename stream_it_t, 358 void write_id(stream_it_t & stream_it, 359 sequence_file_output_options const & options, 362 if (options.fasta_legacy_id_marker) 367 if (options.fasta_blank_before_id) 370 std::ranges::copy(id, stream_it); 372 detail::write_eol(stream_it, options.add_carriage_return); 376 template <typename stream_it_t, 378 void write_seq(stream_it_t & stream_it, 379 sequence_file_output_options const & options, 382 if (options.fasta_letters_per_line > 0) 384 #if SEQAN3_WORKAROUND_VIEW_PERFORMANCE 388 stream_it = to_char(c); 389 if (++count % options.fasta_letters_per_line == 0) 390 detail::write_eol(stream_it, options.add_carriage_return); 392 if (count % options.fasta_letters_per_line != 0) 393 detail::write_eol(stream_it, options.add_carriage_return); 395 #else // ↑↑↑ WORKAROUND | ORIGINAL ↓↓↓ 397 //TODO: combining chunk and join is substantially faster than view::interleave (2.5x), why? 398 std::ranges::copy(seq | view::to_char 399 | ranges::view::chunk(options.fasta_letters_per_line) 400 | std::view::join(options.add_carriage_return 401 ? std::string_view{"\r\n"} 402 : std::string_view{"\n"}), 404 detail::write_eol(stream_it, options.add_carriage_return); 405 #endif // SEQAN3_WORKAROUND_VIEW_PERFORMANCE 409 // No performance workaround here, because transform views alone are fast 410 std::ranges::copy(seq | view::to_char, stream_it); 411 detail::write_eol(stream_it, options.add_carriage_return); 416 } // namespace seqan3::detail
Provides seqan3::view::istreambuf.
Provides various shortcuts for common std::ranges functions.
Provides seqan3::detail::ignore_output_iterator for writing to null stream.
constexpr auto istreambuf
A view factory that returns a view over the stream buffer of an input stream.
Definition: istreambuf.hpp:245
Provides seqan3::view::take.
The main SeqAn3 namespace.
Provides seqan3::dna5, container aliases and string literals.
Provides seqan3::view::take_line and seqan3::view::take_line_or_throw.
Provides seqan3::sequence_file_output_options.
Provides seqan3::view::take_until and seqan3::view::take_until_or_throw.
Provides various utility functions.
Provides various utility functions.
Provides seqan3::view::char_to.
Adaptations of concepts from the Ranges TS.
Definition: aligned_sequence_concept.hpp:35
Provides character predicates for tokenisation.
Provides seqan3::ostream and seqan3::ostreambuf iterator.
Adaptations of algorithms from the Ranges TS.
Provides seqan3::view::to_char.
Provides various transformation traits used by the range module.
Provides aliases for qualified.
Provides seqan3::view::take_exactly and seqan3::view::take_exactly_or_throw.