Skip to content

Commit

Permalink
[FEATURE] introduce new concepts seqan3::detail::(writable_)pairwise_…
Browse files Browse the repository at this point in the history
…alignment

This PR finishes task seqan/product_backlog#60
by implementing seqan3::detail::(writable_)pairwise_alignment.
  • Loading branch information
marehr committed Feb 2, 2021
1 parent 1ce2628 commit e0d0420
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
94 changes: 94 additions & 0 deletions include/seqan3/alignment/detail/pairwise_alignment_concept.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// -----------------------------------------------------------------------------------------------------
// 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::detail::pairwise_alignment and seqan3::detail::writable_pairwise_alignment.
* \author Marcel Ehrhardt <marcel.ehrhardt AT fu-berlin.de>
*/

#pragma once

#include <tuple>

#include <seqan3/alignment/aligned_sequence/aligned_sequence_concept.hpp>
#if SEQAN3_WORKAROUND_ISSUE_286
#include <seqan3/core/detail/transfer_type_modifier_onto.hpp>
#endif // SEQAN3_WORKAROUND_ISSUE_286

namespace seqan3::detail
{

/*!\interface seqan3::detail::pairwise_alignment < >
* \extends seqan3::pair_like
* \ingroup alignment
* \brief A concept that models a pairwise alignment type.
*
* \details
*
* A pairwise alignment is a seqan3::pair_like of two seqan3::aligned_sequence's.
*/
//!\cond
template <typename pairwise_alignment_t>
SEQAN3_CONCEPT pairwise_alignment =
pair_like<pairwise_alignment_t> &&
#if SEQAN3_WORKAROUND_ISSUE_286
aligned_sequence<
// simulate that tuple_element transfers const over to it's inner members.
transfer_type_modifier_onto_t<
std::remove_reference_t<pairwise_alignment_t>,
std::tuple_element_t<0, std::remove_cvref_t<pairwise_alignment_t>>
>
> &&
aligned_sequence<
// simulate that tuple_element transfers const over to it's inner members.
transfer_type_modifier_onto_t<
std::remove_reference_t<pairwise_alignment_t>,
std::tuple_element_t<1, std::remove_cvref_t<pairwise_alignment_t>>
>
>;
#else // ^^^ workaround / no workaround vvv
aligned_sequence<std::tuple_element_t<0, std::remove_reference_t<pairwise_alignment_t>>> &&
aligned_sequence<std::tuple_element_t<1, std::remove_reference_t<pairwise_alignment_t>>>;
#endif // SEQAN3_WORKAROUND_ISSUE_286

//!\endcond

/*!\interface seqan3::detail::writable_pairwise_alignment < >
* \extends seqan3::detail::pairwise_alignment
* \ingroup alignment
* \brief A concept that models a writable pairwise alignment type.
*
* \details
*
* A writable pairwise alignment is a seqan3::pair_like of two seqan3::writable_aligned_sequence's.
*/
//!\cond
template <typename pairwise_alignment_t>
SEQAN3_CONCEPT writable_pairwise_alignment =
pairwise_alignment<pairwise_alignment_t> &&
#if SEQAN3_WORKAROUND_ISSUE_286
writable_aligned_sequence<
// simulate that tuple_element transfers const over to it's inner members.
transfer_type_modifier_onto_t<
std::remove_reference_t<pairwise_alignment_t>,
std::tuple_element_t<0, std::remove_cvref_t<pairwise_alignment_t>>
>
> &&
writable_aligned_sequence<
// simulate that tuple_element transfers const over to it's inner members.
transfer_type_modifier_onto_t<
std::remove_reference_t<pairwise_alignment_t>,
std::tuple_element_t<1, std::remove_cvref_t<pairwise_alignment_t>>
>
>;
#else // ^^^ workaround / no workaround vvv
writable_aligned_sequence<std::tuple_element_t<0, std::remove_reference_t<pairwise_alignment_t>>> &&
writable_aligned_sequence<std::tuple_element_t<1, std::remove_reference_t<pairwise_alignment_t>>>;
#endif // SEQAN3_WORKAROUND_ISSUE_286
//!\endcond

} // namespace seqan3::detail
9 changes: 9 additions & 0 deletions include/seqan3/core/platform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@
# define SEQAN3_WORKAROUND_VIEW_PERFORMANCE 1
#endif

//!\brief See https://github.com/seqan/product_backlog/issues/286
#ifndef SEQAN3_WORKAROUND_ISSUE_286
# if defined(__GNUC__) && (__GNUC__ <= 9)
# define SEQAN3_WORKAROUND_ISSUE_286 1
# else
# define SEQAN3_WORKAROUND_ISSUE_286 0
# endif
#endif

//!\brief See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87113
#ifndef SEQAN3_WORKAROUND_GCC_87113
# if defined(__GNUC_MINOR__) && ((__GNUC__ == 7) || ((__GNUC__ == 8) && (__GNUC_MINOR__ < 3)))
Expand Down
1 change: 1 addition & 0 deletions test/unit/alignment/detail/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
seqan3_test(pairwise_alignment_concept_test.cpp)
109 changes: 109 additions & 0 deletions test/unit/alignment/detail/pairwise_alignment_concept_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// -----------------------------------------------------------------------------------------------------
// 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
// -----------------------------------------------------------------------------------------------------

#include <gtest/gtest.h>

#include <seqan3/alignment/detail/pairwise_alignment_concept.hpp>
#include <seqan3/alphabet/gap/gapped.hpp>
#include <seqan3/alphabet/nucleotide/dna4.hpp>
#include <seqan3/alphabet/nucleotide/dna5.hpp>

TEST(pairwise_alignment_concept, std_pair_gapped_sequences)
{
using gapped_sequence1_t = std::vector<seqan3::gapped<seqan3::dna4>>;
using gapped_sequence2_t = std::vector<seqan3::gapped<seqan3::dna4>>;
using alignment_t = std::pair<gapped_sequence1_t, gapped_sequence2_t>;

EXPECT_FALSE((seqan3::detail::pairwise_alignment<gapped_sequence1_t>));
EXPECT_FALSE((seqan3::detail::pairwise_alignment<gapped_sequence2_t>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t &>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const &>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t &&>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const &&>));
}

TEST(pairwise_alignment_concept, std_tuple_gapped_sequences)
{
using gapped_sequence1_t = std::vector<seqan3::gapped<seqan3::dna4>> const;
using gapped_sequence2_t = std::vector<seqan3::gapped<seqan3::dna5>>;
using alignment_t = std::tuple<gapped_sequence1_t, gapped_sequence2_t>;

EXPECT_FALSE((seqan3::detail::pairwise_alignment<gapped_sequence1_t>));
EXPECT_FALSE((seqan3::detail::pairwise_alignment<gapped_sequence2_t>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t &>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const &>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t &&>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const &&>));
}

TEST(pairwise_alignment_concept, std_tuple_gap_sequence)
{
using gap_sequence1_t = std::vector<seqan3::gap> const;
using gap_sequence2_t = std::vector<seqan3::gap>;
using alignment_t = std::tuple<gap_sequence1_t, gap_sequence2_t>;

EXPECT_FALSE((seqan3::detail::pairwise_alignment<gap_sequence1_t>));
EXPECT_FALSE((seqan3::detail::pairwise_alignment<gap_sequence2_t>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t &>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const &>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t &&>));
EXPECT_TRUE((seqan3::detail::pairwise_alignment<alignment_t const &&>));
}

TEST(writable_pairwise_alignment_concept, std_pair_gapped_sequences)
{
using gapped_sequence1_t = std::vector<seqan3::gapped<seqan3::dna4>>;
using gapped_sequence2_t = std::vector<seqan3::gapped<seqan3::dna4>>;
using alignment_t = std::pair<gapped_sequence1_t, gapped_sequence2_t>;

EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<gapped_sequence1_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<gapped_sequence2_t>));
EXPECT_TRUE((seqan3::detail::writable_pairwise_alignment<alignment_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const>));
EXPECT_TRUE((seqan3::detail::writable_pairwise_alignment<alignment_t &>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const &>));
EXPECT_TRUE((seqan3::detail::writable_pairwise_alignment<alignment_t &&>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const &&>));
}

TEST(writable_pairwise_alignment_concept, std_tuple_gapped_sequences)
{
using gapped_sequence1_t = std::vector<seqan3::gapped<seqan3::dna4>>;
using gapped_sequence2_t = std::vector<seqan3::gapped<seqan3::dna5>> const;
using alignment_t = std::tuple<gapped_sequence1_t, gapped_sequence2_t>;

EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<gapped_sequence1_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<gapped_sequence2_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t &>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const &>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t &&>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const &&>));
}

TEST(writable_pairwise_alignment_concept, std_tuple_gap_sequence)
{
using gap_sequence1_t = std::vector<seqan3::gap>;
using gap_sequence2_t = std::vector<seqan3::gap> const;
using alignment_t = std::tuple<gap_sequence1_t, gap_sequence2_t>;

EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<gap_sequence1_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<gap_sequence2_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t &>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const &>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t &&>));
EXPECT_FALSE((seqan3::detail::writable_pairwise_alignment<alignment_t const &&>));
}

0 comments on commit e0d0420

Please sign in to comment.