Skip to content

Commit

Permalink
Merge bc86c46 into a1d5d4d
Browse files Browse the repository at this point in the history
  • Loading branch information
marehr committed Feb 15, 2021
2 parents a1d5d4d + bc86c46 commit 1495d4b
Show file tree
Hide file tree
Showing 6 changed files with 379 additions and 4 deletions.
6 changes: 3 additions & 3 deletions include/seqan3/io/structure_file/input.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
#include <seqan3/io/stream/concept.hpp>
#include <seqan3/io/exception.hpp>
#include <seqan3/std/filesystem>
#include <seqan3/io/record.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/structure_file/input_format_concept.hpp>
#include <seqan3/io/structure_file/input_options.hpp>
#include <seqan3/io/structure_file/format_vienna.hpp>
#include <seqan3/io/structure_file/record.hpp>
#include <seqan3/utility/type_list/traits.hpp>

namespace seqan3
Expand Down Expand Up @@ -546,8 +546,8 @@ class structure_file_input
react_type, react_type, comment_type, offset_type>;

//!\brief The type of the record, a specialisation of seqan3::record; acts as a tuple of the selected field types.
using record_type = record<detail::select_types_with_ids_t<field_types, field_ids, selected_field_ids>,
selected_field_ids>;
using record_type = structure_record<detail::select_types_with_ids_t<field_types, field_ids, selected_field_ids>,
selected_field_ids>;
//!\}

/*!\name Range associated types
Expand Down
190 changes: 190 additions & 0 deletions include/seqan3/io/structure_file/record.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// -----------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
// -----------------------------------------------------------------------------------------------------

/*!\file
* \brief Provides seqan3::structure_record.
* \author Marcel Ehrhardt <marcel.ehrhardt AT fu-berlin.de>
*/

#pragma once

#include <seqan3/io/record.hpp>

namespace seqan3
{
/*!\brief The record type of seqan3::structure_file_input.
* \ingroup structure_file
* \implements seqan3::detail::record_like
* \tparam field_types The types of the fields in this record as a seqan3::type_list.
* \tparam field_ids A seqan3::fields type with seqan3::field IDs corresponding to field_types.
*/
template <typename field_types, typename field_ids>
class structure_record : public record<field_types, field_ids>
{
//!\brief The base class.
using base_t = record<field_types, field_ids>;

//!\brief The underlying std::tuple class.
using tuple_base_t = typename base_t::base_type;

//!\copydoc seqan3::record::field_constant
template <field f>
using field_constant = typename base_t::template field_constant<f>;

using base_t::get_impl;
public:
/*!\name Constructors, destructor and assignment
* \{
*/
structure_record() = default; //!< Defaulted.
structure_record(structure_record const &) = default; //!< Defaulted.
structure_record & operator=(structure_record const &) = default; //!< Defaulted.
structure_record(structure_record &&) = default; //!< Defaulted.
structure_record & operator=(structure_record &&) = default; //!< Defaulted.
~structure_record() = default; //!< Defaulted.

//!\brief Inherit std::tuple's and seqan3::record constructors.
using base_t::base_t;
//!\}

//!\brief The identifier, usually a string.
decltype(auto) id() &&
{
return get_impl(field_constant<seqan3::field::id>{}, static_cast<tuple_base_t &&>(*this));
}
//!\copydoc seqan3::structure_record::id
decltype(auto) id() const &&
{
return get_impl(field_constant<seqan3::field::id>{}, static_cast<tuple_base_t const &&>(*this));
}
//!\copydoc seqan3::structure_record::id
decltype(auto) id() &
{
return get_impl(field_constant<seqan3::field::id>{}, static_cast<tuple_base_t &>(*this));
}
//!\copydoc seqan3::structure_record::id
decltype(auto) id() const &
{
return get_impl(field_constant<seqan3::field::id>{}, static_cast<tuple_base_t const &>(*this));
}

//!\brief The "sequence", usually a range of nucleotides or amino acids.
decltype(auto) sequence() &&
{
return get_impl(field_constant<seqan3::field::seq>{}, static_cast<tuple_base_t &&>(*this));
}
//!\copydoc seqan3::structure_record::sequence
decltype(auto) sequence() const &&
{
return get_impl(field_constant<seqan3::field::seq>{}, static_cast<tuple_base_t const &&>(*this));
}
//!\copydoc seqan3::structure_record::sequence
decltype(auto) sequence() &
{
return get_impl(field_constant<seqan3::field::seq>{}, static_cast<tuple_base_t &>(*this));
}
//!\copydoc seqan3::structure_record::sequence
decltype(auto) sequence() const &
{
return get_impl(field_constant<seqan3::field::seq>{}, static_cast<tuple_base_t const &>(*this));
}

//!\brief Fixed interactions, usually a string of structure alphabet characters.
decltype(auto) sequence_structure() &&
{
return get_impl(field_constant<seqan3::field::structure>{}, static_cast<tuple_base_t &&>(*this));
}
//!\copydoc seqan3::structure_record::sequence_structure
decltype(auto) sequence_structure() const &&
{
return get_impl(field_constant<seqan3::field::structure>{}, static_cast<tuple_base_t const &&>(*this));
}
//!\copydoc seqan3::structure_record::sequence_structure
decltype(auto) sequence_structure() &
{
return get_impl(field_constant<seqan3::field::structure>{}, static_cast<tuple_base_t &>(*this));
}
//!\copydoc seqan3::structure_record::sequence_structure
decltype(auto) sequence_structure() const &
{
return get_impl(field_constant<seqan3::field::structure>{}, static_cast<tuple_base_t const &>(*this));
}

//!\brief Energy of a folded sequence, represented by one float number.
decltype(auto) energy() &&
{
return get_impl(field_constant<seqan3::field::energy>{}, static_cast<tuple_base_t &&>(*this));
}
//!\copydoc seqan3::structure_record::energy
decltype(auto) energy() const &&
{
return get_impl(field_constant<seqan3::field::energy>{}, static_cast<tuple_base_t const &&>(*this));
}
//!\copydoc seqan3::structure_record::energy
decltype(auto) energy() &
{
return get_impl(field_constant<seqan3::field::energy>{}, static_cast<tuple_base_t &>(*this));
}
//!\copydoc seqan3::structure_record::energy
decltype(auto) energy() const &
{
return get_impl(field_constant<seqan3::field::energy>{}, static_cast<tuple_base_t const &>(*this));
}

//!\brief Base pair probability matrix of interactions, usually a matrix of float numbers.
decltype(auto) base_pair_probability_matrix() &&
{
// this is computed
return get_impl(field_constant<seqan3::field::bpp>{}, static_cast<tuple_base_t &&>(*this));
}
//!\copydoc seqan3::structure_record::base_pair_probability_matrix
decltype(auto) base_pair_probability_matrix() const &&
{
return get_impl(field_constant<seqan3::field::bpp>{}, static_cast<tuple_base_t const &&>(*this));
}
//!\copydoc seqan3::structure_record::base_pair_probability_matrix
decltype(auto) base_pair_probability_matrix() &
{
return get_impl(field_constant<seqan3::field::bpp>{}, static_cast<tuple_base_t &>(*this));
}
//!\copydoc seqan3::structure_record::base_pair_probability_matrix
decltype(auto) base_pair_probability_matrix() const &
{
return get_impl(field_constant<seqan3::field::bpp>{}, static_cast<tuple_base_t const &>(*this));
}

// decltype(auto) reactivity(); // unused
// decltype(auto) reactivity_errors(); // unused
// decltype(auto) comment(); // unused
// decltype(auto) base_qualities(); // unused
};
} // namespace seqan3

namespace std
{

/*!\brief Provides access to the number of elements in a tuple as a compile-time constant expression.
* \implements seqan3::unary_type_trait
* \relates seqan3::structure_record
* \see std::tuple_size_v
*/
template <typename field_types, typename field_ids>
struct tuple_size<seqan3::structure_record<field_types, field_ids>>
: tuple_size<typename seqan3::structure_record<field_types, field_ids>::base_type>
{};

/*!\brief Obtains the type of the specified element.
* \implements seqan3::transformation_trait
* \relates seqan3::structure_record
* \see [std::tuple_element](https://en.cppreference.com/w/cpp/utility/tuple/tuple_element)
*/
template <size_t elem_no, typename field_types, typename field_ids>
struct tuple_element<elem_no, seqan3::structure_record<field_types, field_ids>>
: tuple_element<elem_no, typename seqan3::structure_record<field_types, field_ids>::base_type>
{};

} // namespace std
1 change: 1 addition & 0 deletions test/unit/io/structure_file/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
seqan3_test(format_vienna_test.cpp)
seqan3_test(structure_file_input_test.cpp)
seqan3_test(structure_file_output_test.cpp)
seqan3_test(structure_file_record_test.cpp)
12 changes: 12 additions & 0 deletions test/unit/io/structure_file/format_vienna_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,25 +124,31 @@ struct read : public ::testing::Test
for (size_t idx = 0ul; idx < expected_seq.size(); ++idx, ++it)
{
EXPECT_EQ(check_energy, seqan3::get<seqan3::field::energy>(*it).has_value());
EXPECT_EQ(check_energy, (*it).energy().has_value());
if (check_seq)
{
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::seq>(*it), expected_seq[idx]);
EXPECT_RANGE_EQ((*it).sequence(), expected_seq[idx]);
}
if (check_id)
{
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::id>(*it), expected_id[idx]);
EXPECT_RANGE_EQ((*it).id(), expected_id[idx]);
}
if (check_structure)
{
bpp_test(seqan3::get<seqan3::field::bpp>(*it), expected_interactions[idx]);
bpp_test((*it).base_pair_probability_matrix(), expected_interactions[idx]);
}
if (check_energy)
{
EXPECT_DOUBLE_EQ(*seqan3::get<seqan3::field::energy>(*it), expected_energy[idx]);
EXPECT_DOUBLE_EQ(*(*it).energy(), expected_energy[idx]);
}
if (check_structure)
{
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::structure>(*it), expected_structure[idx]);
EXPECT_RANGE_EQ((*it).sequence_structure(), expected_structure[idx]);
}
}
}
Expand Down Expand Up @@ -251,6 +257,7 @@ TEST_F(read_fields, only_seq)
for (size_t idx = 0ul; idx < expected_seq.size(); ++idx, ++it)
{
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::seq>(*it), expected_seq[idx]);
EXPECT_RANGE_EQ((*it).sequence(), expected_seq[idx]);
}
}

Expand All @@ -262,6 +269,7 @@ TEST_F(read_fields, only_id)
for (size_t idx = 0ul; idx < expected_seq.size(); ++idx, ++it)
{
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::id>(*it), expected_id[idx]);
EXPECT_RANGE_EQ((*it).id(), expected_id[idx]);
}
}

Expand All @@ -273,6 +281,7 @@ TEST_F(read_fields, only_structure)
for (size_t idx = 0ul; idx < expected_seq.size(); ++idx, ++it)
{
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::structure>(*it), expected_structure[idx]);
EXPECT_RANGE_EQ((*it).sequence_structure(), expected_structure[idx]);
}
}

Expand All @@ -284,7 +293,9 @@ TEST_F(read_fields, only_energy)
for (size_t idx = 0ul; idx < expected_seq.size(); ++idx, ++it)
{
EXPECT_TRUE(seqan3::get<seqan3::field::energy>(*it));
EXPECT_TRUE((*it).energy());
EXPECT_DOUBLE_EQ(*seqan3::get<seqan3::field::energy>(*it), expected_energy[idx]);
EXPECT_DOUBLE_EQ(*(*it).energy(), expected_energy[idx]);
}
}

Expand All @@ -310,6 +321,7 @@ TEST_F(read_fields, only_bpp)
for (size_t idx = 0ul; idx < expected_seq.size(); ++idx, ++it)
{
bpp_test(seqan3::get<seqan3::field::bpp>(*it), expected_interactions[idx]);
bpp_test((*it).base_pair_probability_matrix(), expected_interactions[idx]);
}
}

Expand Down
19 changes: 18 additions & 1 deletion test/unit/io/structure_file/structure_file_input_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ struct structure_file_input_read : public ::testing::Test
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::seq>(rec), seq_comp[counter]);
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::id>(rec), id_comp[counter]);
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::structure>(rec), structure_comp[counter]);

EXPECT_RANGE_EQ(rec.sequence(), seq_comp[counter]);
EXPECT_RANGE_EQ(rec.id(), id_comp[counter]);
EXPECT_RANGE_EQ(rec.sequence_structure(), structure_comp[counter]);

++counter;
}

Expand Down Expand Up @@ -305,6 +310,11 @@ TEST_F(structure_file_input_read, record_general)
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::seq>(rec), seq_comp[counter]);
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::id>(rec), id_comp[counter]);
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::structure>(rec), structure_comp[counter]);

EXPECT_RANGE_EQ(rec.sequence(), seq_comp[counter]);
EXPECT_RANGE_EQ(rec.id(), id_comp[counter]);
EXPECT_RANGE_EQ(rec.sequence_structure(), structure_comp[counter]);

++counter;
}
EXPECT_EQ(counter, num_records);
Expand Down Expand Up @@ -365,7 +375,7 @@ TEST_F(structure_file_input_read, record_file_view)
#if !SEQAN3_WORKAROUND_GCC_93983
auto minimum_length_filter = std::views::filter([] (auto const & rec)
{
return size(seqan3::get<seqan3::field::seq>(rec)) >= 5;
return size(rec.sequence()) >= 5;
});
#endif

Expand All @@ -381,6 +391,13 @@ TEST_F(structure_file_input_read, record_file_view)
bpp_test(seqan3::get<seqan3::field::bpp>(rec), interaction_comp[counter]);
EXPECT_RANGE_EQ(seqan3::get<seqan3::field::structure>(rec), structure_comp[counter]);
EXPECT_DOUBLE_EQ(seqan3::get<seqan3::field::energy>(rec).value(), energy_comp[counter]);

EXPECT_RANGE_EQ(rec.sequence(), seq_comp[counter]);
EXPECT_RANGE_EQ(rec.id(), id_comp[counter]);
bpp_test(rec.base_pair_probability_matrix(), interaction_comp[counter]);
EXPECT_RANGE_EQ(rec.sequence_structure(), structure_comp[counter]);
EXPECT_DOUBLE_EQ(rec.energy().value(), energy_comp[counter]);

++counter;
}
EXPECT_EQ(counter, num_records);
Expand Down
Loading

0 comments on commit 1495d4b

Please sign in to comment.