Loading...
Searching...
No Matches
sequence_file/input.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <cassert>
#include <filesystem>
#include <fstream>
#include <string>
#include <variant>
#include <vector>
#include <seqan3/alphabet/adaptation/char.hpp>
#include <seqan3/alphabet/aminoacid/aa27.hpp>
#include <seqan3/alphabet/nucleotide/dna15.hpp>
#include <seqan3/alphabet/nucleotide/dna5.hpp>
#include <seqan3/alphabet/quality/phred42.hpp>
#include <seqan3/alphabet/quality/qualified.hpp>
#include <seqan3/io/detail/in_file_iterator.hpp>
#include <seqan3/io/detail/misc_input.hpp>
#include <seqan3/io/detail/record.hpp>
#include <seqan3/io/exception.hpp>
#include <seqan3/io/sam_file/format_sam.hpp>
#include <seqan3/io/sequence_file/format_embl.hpp>
#include <seqan3/io/sequence_file/format_fasta.hpp>
#include <seqan3/io/sequence_file/format_fastq.hpp>
#include <seqan3/io/sequence_file/format_genbank.hpp>
#include <seqan3/io/sequence_file/input_format_concept.hpp>
#include <seqan3/io/sequence_file/record.hpp>
#include <seqan3/io/stream/concept.hpp>
#include <seqan3/utility/type_list/traits.hpp>
namespace seqan3
{
// ----------------------------------------------------------------------------
// sequence_file_input_traits
// ----------------------------------------------------------------------------
template <typename t>
concept sequence_file_input_traits = requires (t v) {
requires writable_alphabet<typename t::sequence_alphabet>;
requires writable_alphabet<typename t::sequence_legal_alphabet>;
requires detail::is_char_adaptation_v<typename t::sequence_alphabet>
|| explicitly_convertible_to<typename t::sequence_legal_alphabet, typename t::sequence_alphabet>;
requires sequence_container<typename t::template sequence_container<typename t::sequence_alphabet>>;
requires writable_alphabet<typename t::id_alphabet>;
requires sequence_container<typename t::template id_container<typename t::id_alphabet>>;
requires writable_quality_alphabet<typename t::quality_alphabet>;
requires sequence_container<typename t::template quality_container<typename t::quality_alphabet>>;
};
// ----------------------------------------------------------------------------
// sequence_file_input_default_traits
// ----------------------------------------------------------------------------
struct sequence_file_input_default_traits_dna
{
using sequence_alphabet = dna5;
using sequence_legal_alphabet = dna15;
template <typename _sequence_alphabet>
using sequence_container = std::vector<_sequence_alphabet>;
using id_alphabet = char;
template <typename _id_alphabet>
using id_container = std::basic_string<_id_alphabet>;
using quality_alphabet = phred42;
template <typename _quality_alphabet>
using quality_container = std::vector<_quality_alphabet>;
};
struct sequence_file_input_default_traits_aa : sequence_file_input_default_traits_dna
{
using sequence_alphabet = aa27;
using sequence_legal_alphabet = aa27;
};
// ----------------------------------------------------------------------------
// sequence_file_input
// ----------------------------------------------------------------------------
template <sequence_file_input_traits traits_type_ = sequence_file_input_default_traits_dna,
detail::fields_specialisation selected_field_ids_ = fields<field::seq, field::id, field::qual>,
detail::type_list_of_sequence_file_input_formats valid_formats_ =
type_list<format_embl, format_fasta, format_fastq, format_genbank, format_sam>>
class sequence_file_input
{
public:
using traits_type = traits_type_;
using selected_field_ids = selected_field_ids_;
using valid_formats = valid_formats_;
using stream_char_type = char;
using field_ids = fields<field::seq, field::id, field::qual>;
static_assert(
[]() constexpr
{
for (field f : selected_field_ids::as_array)
if (!field_ids::contains(f))
return false;
return true;
}(),
"You selected a field that is not valid for sequence files, please refer to the documentation "
"of sequence_file_input::field_ids for the accepted values.");
using sequence_type = typename traits_type::template sequence_container<typename traits_type::sequence_alphabet>;
using id_type = typename traits_type::template id_container<typename traits_type::id_alphabet>;
using quality_type = typename traits_type::template quality_container<typename traits_type::quality_alphabet>;
using field_types = type_list<sequence_type, id_type, quality_type>;
using record_type = sequence_record<detail::select_types_with_ids_t<field_types, field_ids, selected_field_ids>,
selected_field_ids>;
using value_type = record_type;
using reference = record_type &;
using const_reference = void;
using size_type = size_t;
using difference_type = std::make_signed_t<size_t>;
using iterator = detail::in_file_iterator<sequence_file_input>;
using const_iterator = void;
using sentinel = std::default_sentinel_t;
sequence_file_input() = delete;
sequence_file_input(sequence_file_input const &) = delete;
sequence_file_input & operator=(sequence_file_input const &) = delete;
sequence_file_input(sequence_file_input &&) = default;
sequence_file_input & operator=(sequence_file_input &&) = default;
~sequence_file_input() = default;
sequence_file_input(std::filesystem::path filename,
selected_field_ids const & SEQAN3_DOXYGEN_ONLY(fields_tag) = selected_field_ids{}) :
primary_stream{new std::ifstream{}, stream_deleter_default}
{
primary_stream->rdbuf()->pubsetbuf(stream_buffer.data(), stream_buffer.size());
static_cast<std::basic_ifstream<char> *>(primary_stream.get())
->open(filename, std::ios_base::in | std::ios::binary);
if (!primary_stream->good())
throw file_open_error{"Could not open file " + filename.string() + " for reading."};
// possibly add intermediate compression stream
secondary_stream = detail::make_secondary_istream(*primary_stream, filename);
// initialise format handler or throw if format is not found
using format_variant_t =
typename detail::variant_from_tags<valid_formats, detail::sequence_file_input_format_exposer>::type;
format_variant_t format_variant{};
detail::set_format(format_variant, filename);
std::visit(
[&](auto && selected_format)
{
using format_t = std::remove_cvref_t<decltype(selected_format)>;
format = std::make_unique<selected_sequence_format<format_t>>();
},
format_variant);
}
/* NOTE(h-2): Curiously we do not need a user-defined deduction guide for the above constructor.
* A combination of default template parameters and auto-deduction guides works as expected,
* independent of whether the second/optional parameter is specified or not, i.e. it is possible
* to auto-deduct and overwrite a single template parameter out of the four if the optional parameter
* is specified and use the default otherwise.
*/
template <input_stream stream_t, sequence_file_input_format file_format>
requires std::same_as<typename std::remove_reference_t<stream_t>::char_type, stream_char_type>
sequence_file_input(stream_t & stream,
file_format const & SEQAN3_DOXYGEN_ONLY(format_tag),
selected_field_ids const & SEQAN3_DOXYGEN_ONLY(fields_tag) = selected_field_ids{}) :
primary_stream{&stream, stream_deleter_noop},
format{std::make_unique<selected_sequence_format<file_format>>()}
{
static_assert(list_traits::contains<file_format, valid_formats>,
"You selected a format that is not in the valid_formats of this file.");
// possibly add intermediate compression stream
secondary_stream = detail::make_secondary_istream(*primary_stream);
}
template <input_stream stream_t, sequence_file_input_format file_format>
requires std::same_as<typename std::remove_reference_t<stream_t>::char_type, stream_char_type>
sequence_file_input(stream_t && stream,
file_format const & SEQAN3_DOXYGEN_ONLY(format_tag),
selected_field_ids const & SEQAN3_DOXYGEN_ONLY(fields_tag) = selected_field_ids{}) :
primary_stream{new stream_t{std::move(stream)}, stream_deleter_default},
format{std::make_unique<selected_sequence_format<file_format>>()}
{
static_assert(list_traits::contains<file_format, valid_formats>,
"You selected a format that is not in the valid_formats of this file.");
// possibly add intermediate compression stream
secondary_stream = detail::make_secondary_istream(*primary_stream);
}
iterator begin()
{
// buffer first record
if (!first_record_was_read)
{
read_next_record();
first_record_was_read = true;
}
return {*this};
}
sentinel end() noexcept
{
return {};
}
reference front() noexcept
{
return *begin();
}
using sequence_file_input_options_type = sequence_file_input_options<typename traits_type::sequence_legal_alphabet>;
sequence_file_input_options_type options;
protected:
record_type record_buffer;
std::vector<char> stream_buffer{std::vector<char>(1'000'000)};
std::streampos position_buffer{};
using stream_ptr_t = std::unique_ptr<std::basic_istream<stream_char_type>,
std::function<void(std::basic_istream<stream_char_type> *)>>;
static void stream_deleter_noop(std::basic_istream<stream_char_type> *)
{}
static void stream_deleter_default(std::basic_istream<stream_char_type> * ptr)
{
delete ptr;
}
stream_ptr_t primary_stream{nullptr, stream_deleter_noop};
stream_ptr_t secondary_stream{nullptr, stream_deleter_noop};
bool first_record_was_read{false};
bool at_end{false};
private:
void read_next_record()
{
// clear the record
record_buffer.clear();
// at end if we could not read further
if ((std::istreambuf_iterator<stream_char_type>{*secondary_stream}
== std::istreambuf_iterator<stream_char_type>{}))
{
at_end = true;
return;
}
format->read_sequence_record(*secondary_stream, record_buffer, position_buffer, options);
}
struct sequence_format_base
{
sequence_format_base() = default;
sequence_format_base(sequence_format_base const &) = default;
sequence_format_base(sequence_format_base &&) = default;
sequence_format_base & operator=(sequence_format_base const &) = default;
sequence_format_base & operator=(sequence_format_base &&) = default;
virtual ~sequence_format_base() = default;
virtual void read_sequence_record(std::istream & instream,
record_type & record_buffer,
std::streampos & position_buffer,
sequence_file_input_options_type const & options) = 0;
};
template <typename format_t>
struct selected_sequence_format final : public sequence_format_base
{
selected_sequence_format() = default;
selected_sequence_format(selected_sequence_format const &) = default;
selected_sequence_format(selected_sequence_format &&) = default;
selected_sequence_format & operator=(selected_sequence_format const &) = default;
selected_sequence_format & operator=(selected_sequence_format &&) = default;
~selected_sequence_format() = default;
void read_sequence_record(std::istream & instream,
record_type & record_buffer,
std::streampos & position_buffer,
sequence_file_input_options_type const & options) override
{
// read new record
{
_format.read_sequence_record(instream,
options,
position_buffer,
detail::get_or_ignore<field::seq>(record_buffer),
detail::get_or_ignore<field::id>(record_buffer),
detail::get_or_ignore<field::qual>(record_buffer));
}
}
detail::sequence_file_input_format_exposer<format_t> _format{};
};
std::unique_ptr<sequence_format_base> format{};
friend iterator;
};
template <input_stream stream_type, sequence_file_input_format file_format>
sequence_file_input(stream_type & stream,
file_format const &)
-> sequence_file_input<typename sequence_file_input<>::traits_type, // actually use the default
typename sequence_file_input<>::selected_field_ids, // default field ids.
type_list<file_format>>;
template <input_stream stream_type, sequence_file_input_format file_format>
sequence_file_input(stream_type && stream,
file_format const &)
-> sequence_file_input<typename sequence_file_input<>::traits_type, // actually use the default
typename sequence_file_input<>::selected_field_ids, // default field ids.
type_list<file_format>>;
template <input_stream stream_type,
sequence_file_input_format file_format,
detail::fields_specialisation selected_field_ids>
sequence_file_input(stream_type && stream,
file_format const &,
selected_field_ids const &)
-> sequence_file_input<typename sequence_file_input<>::traits_type, // actually use the default
selected_field_ids,
type_list<file_format>>;
template <input_stream stream_type,
sequence_file_input_format file_format,
detail::fields_specialisation selected_field_ids>
sequence_file_input(stream_type & stream,
file_format const &,
selected_field_ids const &)
-> sequence_file_input<typename sequence_file_input<>::traits_type, // actually use the default
selected_field_ids,
type_list<file_format>>;
} // namespace seqan3
aa27.hpp
Provides seqan3::aa27, container aliases and string literals.
std::basic_ifstream
std::basic_istream
std::basic_string
cassert
char.hpp
Provides alphabet adaptations for standard char types.
seqan3::aa27
The twenty-seven letter amino acid alphabet.
Definition aa27.hpp:43
seqan3::dna15
The 15 letter DNA alphabet, containing all IUPAC smybols minus the gap.
Definition dna15.hpp:48
seqan3::dna5
The five letter DNA alphabet of A,C,G,T and the unknown character N.
Definition dna5.hpp:48
seqan3::phred42
Quality type for traditional Sanger and modern Illumina Phred scores.
Definition phred42.hpp:44
seqan3::sequence_file_input_format
The generic concept for sequence file in formats.
Definition sequence_file/input_format_concept.hpp:91
seqan3::sequence_file_input::const_reference
void const_reference
The const_reference type is void, because files are not const-iterable.
Definition sequence_file/input.hpp:266
seqan3::sequence_file_input::sentinel
std::default_sentinel_t sentinel
The type returned by end().
Definition sequence_file/input.hpp:276
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(std::filesystem::path filename, selected_field_ids const &fields_tag=selected_field_ids{})
Construct from filename.
Definition sequence_file/input.hpp:311
seqan3::sequence_file_input::front
reference front() noexcept
Return the record we are currently at in the file.
Definition sequence_file/input.hpp:463
seqan3::sequence_file_input::field_types
type_list< sequence_type, id_type, quality_type > field_types
The previously defined types aggregated in a seqan3::type_list.
Definition sequence_file/input.hpp:250
seqan3::sequence_file_input::field_ids
fields< field::seq, field::id, field::qual > field_ids
The subset of seqan3::field IDs that are valid for this file; order corresponds to the types in field...
Definition sequence_file/input.hpp:225
seqan3::sequence_file_input::value_type
record_type value_type
The value_type is the record_type.
Definition sequence_file/input.hpp:262
seqan3::sequence_file_input::begin
iterator begin()
Returns an iterator to current position in the file.
Definition sequence_file/input.hpp:410
seqan3::sequence_file_input::options
sequence_file_input_options_type options
The options are public and its members can be set directly.
Definition sequence_file/input.hpp:472
seqan3::sequence_file_input::sequence_type
typename traits_type::template sequence_container< typename traits_type::sequence_alphabet > sequence_type
The type of field::seq (std::vector <seqan3::dna5> by default).
Definition sequence_file/input.hpp:244
seqan3::sequence_file_input::end
sentinel end() noexcept
Returns a sentinel for comparison with iterator.
Definition sequence_file/input.hpp:435
seqan3::sequence_file_input::stream_char_type
char stream_char_type
Character type of the stream(s).
Definition sequence_file/input.hpp:219
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(stream_type &stream, file_format const &, selected_field_ids const &) -> sequence_file_input< typename sequence_file_input<>::traits_type, selected_field_ids, type_list< file_format > >
This is an overloaded member function, provided for convenience. It differs from the above function o...
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(stream_type &&stream, file_format const &) -> sequence_file_input< typename sequence_file_input<>::traits_type, typename sequence_file_input<>::selected_field_ids, type_list< file_format > >
This is an overloaded member function, provided for convenience. It differs from the above function o...
seqan3::sequence_file_input::size_type
size_t size_type
An unsigned integer type, usually std::size_t.
Definition sequence_file/input.hpp:268
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(sequence_file_input const &)=delete
Copy construction is explicitly deleted, because you can't have multiple access to the same file.
seqan3::sequence_file_input::iterator
detail::in_file_iterator< sequence_file_input > iterator
The iterator type of this view (an input iterator).
Definition sequence_file/input.hpp:272
seqan3::sequence_file_input::id_type
typename traits_type::template id_container< typename traits_type::id_alphabet > id_type
The type of field::id (std::string by defaul).
Definition sequence_file/input.hpp:246
seqan3::sequence_file_input::~sequence_file_input
~sequence_file_input()=default
Destructor is defaulted.
seqan3::sequence_file_input::reference
record_type & reference
The reference type.
Definition sequence_file/input.hpp:264
seqan3::sequence_file_input::operator=
sequence_file_input & operator=(sequence_file_input &&)=default
Move assignment is defaulted.
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(sequence_file_input &&)=default
Move construction is defaulted.
seqan3::sequence_file_input::const_iterator
void const_iterator
The const iterator type is void, because files are not const-iterable.
Definition sequence_file/input.hpp:274
seqan3::sequence_file_input::operator=
sequence_file_input & operator=(sequence_file_input const &)=delete
Copy assignment is explicitly deleted, because you can't have multiple access to the same file.
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(stream_type &stream, file_format const &) -> sequence_file_input< typename sequence_file_input<>::traits_type, typename sequence_file_input<>::selected_field_ids, type_list< file_format > >
Deduces the sequence input file type from the stream and the format.
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(stream_t &&stream, file_format const &format_tag, selected_field_ids const &fields_tag=selected_field_ids{})
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition sequence_file/input.hpp:378
seqan3::sequence_file_input::sequence_file_input
sequence_file_input()=delete
Default constructor is explicitly deleted, you need to give a stream or file name.
seqan3::sequence_file_input::traits_type
traits_type_ traits_type
A traits type that defines aliases and template for storage of the fields.
Definition sequence_file/input.hpp:213
seqan3::sequence_file_input::selected_field_ids
selected_field_ids_ selected_field_ids
A seqan3::fields list with the fields selected for the record.
Definition sequence_file/input.hpp:215
seqan3::sequence_file_input::sequence_file_input_options_type
sequence_file_input_options< typename traits_type::sequence_legal_alphabet > sequence_file_input_options_type
The input file options type.
Definition sequence_file/input.hpp:470
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(stream_type &&stream, file_format const &, selected_field_ids const &) -> sequence_file_input< typename sequence_file_input<>::traits_type, selected_field_ids, type_list< file_format > >
Deduces the sequence input file type from the stream, the format and the field ids.
seqan3::sequence_file_input::quality_type
typename traits_type::template quality_container< typename traits_type::quality_alphabet > quality_type
The type of field::qual (std::vector <seqan3::phred42> by default).
Definition sequence_file/input.hpp:248
seqan3::sequence_file_input::sequence_file_input
sequence_file_input(stream_t &stream, file_format const &format_tag, selected_field_ids const &fields_tag=selected_field_ids{})
Construct from an existing stream and with specified format.
Definition sequence_file/input.hpp:362
seqan3::sequence_file_input::valid_formats
valid_formats_ valid_formats
A seqan3::type_list with the possible formats.
Definition sequence_file/input.hpp:217
seqan3::sequence_file_input::difference_type
std::make_signed_t< size_t > difference_type
A signed integer type, usually std::ptrdiff_t.
Definition sequence_file/input.hpp:270
seqan3::sequence_file_input::record_type
sequence_record< detail::select_types_with_ids_t< field_types, field_ids, selected_field_ids >, selected_field_ids > record_type
The type of the record, a specialisation of seqan3::record; acts as a tuple of the selected field typ...
Definition sequence_file/input.hpp:253
seqan3::sequence_record
The record type of seqan3::sequence_file_input.
Definition sequence_file/record.hpp:26
std::basic_istream::clear
T clear(T... args)
std::vector::data
T data(T... args)
dna15.hpp
Provides seqan3::dna15, container aliases and string literals.
dna5.hpp
Provides seqan3::dna5, container aliases and string literals.
filesystem
format_embl.hpp
format_fasta.hpp
format_fastq.hpp
format_genbank.hpp
Provides the seqan3::sequence_file_format_genbank class.
format_sam.hpp
Provides the seqan3::format_sam.
std::streampos
fstream
std::function
std::unique_ptr::get
T get(T... args)
seqan3::field
field
An enumerator for the fields used in file formats.
Definition record.hpp:60
seqan3::list_traits::contains
constexpr bool contains
Whether a type occurs in a type list or not.
Definition type_list/traits.hpp:249
in_file_iterator.hpp
Provides the seqan3::detail::in_file_iterator class template.
explicitly_convertible_to
Checks whether from can be explicitly converted to to.
sequence_container
A more refined container concept than seqan3::container.
sequence_file_input_traits
The requirements a traits_type for seqan3::sequence_file_input must meet.
sequence_file_input_traits::sequence_container
using sequence_container
Type template of the seqan3::field::seq, a container template over sequence_alphabet; must satisfy se...
writable_alphabet
Refines seqan3::alphabet and adds assignability.
writable_quality_alphabet
A concept that indicates whether a writable alphabet represents quality scores.
exception.hpp
Provides exceptions used in the I/O module.
concept.hpp
Stream concepts.
std::make_signed_t
std::make_unique
T make_unique(T... args)
misc_input.hpp
Provides various utility functions required only for input.
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
std
SeqAn specific customisations in the standard namespace.
std::basic_ifstream::open
T open(T... args)
std::filesystem::path
phred42.hpp
Provides seqan3::phred42 quality scores.
qualified.hpp
Provides quality alphabet composites.
input_format_concept.hpp
Provides seqan3::sequence_file_input_format and auxiliary classes.
record.hpp
Provides seqan3::sequence_record.
std::vector::size
T size(T... args)
string
seqan3::fields
A class template that holds a choice of seqan3::field.
Definition record.hpp:125
seqan3::file_open_error
Thrown if there is an unspecified filesystem or stream error while opening, e.g. permission problem.
Definition io/exception.hpp:36
seqan3::sequence_file_input_default_traits_aa
A traits type that specifies input as amino acids.
Definition sequence_file/input.hpp:166
seqan3::sequence_file_input_default_traits_aa::sequence_alphabet
aa27 sequence_alphabet
The sequence alphabet is seqan3::aa27.
Definition sequence_file/input.hpp:173
seqan3::sequence_file_input_default_traits_aa::sequence_legal_alphabet
aa27 sequence_legal_alphabet
The legal sequence alphabet for parsing is seqan3::aa27.
Definition sequence_file/input.hpp:176
seqan3::sequence_file_input_default_traits_dna
The default traits for seqan3::sequence_file_input.
Definition sequence_file/input.hpp:130
seqan3::sequence_file_input_default_traits_dna::id_alphabet
char id_alphabet
The alphabet for an identifier string is char.
Definition sequence_file/input.hpp:147
seqan3::sequence_file_input_default_traits_dna::quality_container
std::vector< _quality_alphabet > quality_container
The string type for a quality annotation is std::vector.
Definition sequence_file/input.hpp:158
seqan3::sequence_file_input_default_traits_dna::id_container
std::basic_string< _id_alphabet > id_container
The string type for an identifier is std::basic_string.
Definition sequence_file/input.hpp:151
seqan3::sequence_file_input_default_traits_dna::quality_alphabet
phred42 quality_alphabet
The alphabet for a quality annotation is seqan3::phred42.
Definition sequence_file/input.hpp:154
seqan3::sequence_file_input_default_traits_dna::sequence_legal_alphabet
dna15 sequence_legal_alphabet
The legal sequence alphabet for parsing is seqan3::dna15.
Definition sequence_file/input.hpp:140
seqan3::sequence_file_input_default_traits_dna::sequence_alphabet
dna5 sequence_alphabet
The sequence alphabet is seqan3::dna5.
Definition sequence_file/input.hpp:137
seqan3::sequence_file_input_default_traits_dna::sequence_container
std::vector< _sequence_alphabet > sequence_container
The type of a DNA sequence is std::vector.
Definition sequence_file/input.hpp:144
seqan3::sequence_file_input_options
The options type defines various option members that influence the behaviour of all or some formats.
Definition sequence_file/input_options.hpp:24
seqan3::type_list
Type that contains multiple types.
Definition type_list.hpp:26
traits.hpp
Provides traits for seqan3::type_list.
std::unique_ptr
variant
vector
std::visit
T visit(T... args)
Hide me