Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API] The alignment configuration for the band changed to seqan3::align_cfg::band_fixed_size #1873

Merged
merged 5 commits into from
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ Note that 3.1.0 will be the first API stable release and interfaces in this rele

## API changes

### Alignment

* The alignment configuration elements were refactored:
* The option `seqan3::align_cfg::band` is now renamed to `seqan3::align_cfg::band_fixed_size` and directly initialised
with a `seqan3::align_cfg::lower_diagonal` and `seqan3::align_cfg::upper_diagonal` instead of `seqan3::static_band`.
It also directly exposes the lower_diagonal and upper_diagonal as public members
([\#1873](https://github.com/seqan/seqan3/pull/1873)).

### Core

* In accordance with the standard, the following concepts are renamed:
* `default_constructible` to `default_initializable`
* `readable` to `indirectly_readable`
Expand Down
4 changes: 2 additions & 2 deletions doc/tutorial/pairwise_alignment/configurations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
//! [include_result]

//! [include_band]
#include <seqan3/alignment/band/static_band.hpp>
#include <seqan3/alignment/configuration/align_config_band.hpp>
//! [include_band]

Expand Down Expand Up @@ -92,7 +91,8 @@ auto cfg = seqan3::align_cfg::result{seqan3::with_score};
//! [band]

// Configure a banded alignment.
auto cfg = seqan3::align_cfg::band{seqan3::static_band{seqan3::lower_bound{-4}, seqan3::upper_bound{4}}};
auto cfg = seqan3::align_cfg::band_fixed_size{seqan3::align_cfg::lower_diagonal{-4},
seqan3::align_cfg::upper_diagonal{4}};
//! [band]
(void) cfg;
}
Expand Down
6 changes: 3 additions & 3 deletions doc/tutorial/pairwise_alignment/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,14 @@ In many situations it is not necessary to compute the entire alignment matrix bu
positive impacts on the performance. To limit the computation space the alignment matrix can be bounded by a band.
Thus, only the alignment is computed that fits in this band. Note that this must not be the optimal alignment but in
many cases we can give a rough bound on how similar the sequences will be and therefor use the banded alignment.
To do so, you can use a seqan3::static_band. It will be initialised with a seqan3::lower_bound and a
seqan3::upper_bound. To configure the banded alignment you need to use the seqan3::align_cfg::band configuration.
To do so, you can configure the alignment using the seqan3::align_cfg::band_fixed_size option. This configuration
element will be initialised with a seqan3::align_cfg::lower_diagonal and seqan3::align_cfg::upper_diagonal.

\snippet doc/tutorial/pairwise_alignment/configurations.cpp include_band
\snippet doc/tutorial/pairwise_alignment/configurations.cpp band

\assignment{Assignment 5}
Use the example from assignment 4 and compute it in a band with lower bound set to `-3` and upper bound set to `8`.
Use the example from assignment 4 and compute it in a band with lower diagonal set to `-3` and upper diagonal set to `8`.
How does the result change?

\endassignment
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <utility>

#include <seqan3/alignment/band/static_band.hpp>
#include <seqan3/alignment/pairwise/align_pairwise.hpp>
#include <seqan3/alignment/scoring/nucleotide_scoring_scheme.hpp>
#include <seqan3/alphabet/nucleotide/dna4.hpp>
Expand All @@ -20,7 +19,8 @@ int main()
seqan3::align_cfg::gap{seqan3::gap_scheme{seqan3::gap_score{-4}}} |
seqan3::align_cfg::aligned_ends{seqan3::free_ends_all} |
seqan3::align_cfg::result{seqan3::with_alignment} |
seqan3::align_cfg::band{seqan3::static_band{seqan3::lower_bound{-3}, seqan3::upper_bound{8}}};
seqan3::align_cfg::band_fixed_size{seqan3::align_cfg::lower_diagonal{-3},
seqan3::align_cfg::upper_diagonal{8}};

for (auto const & res : seqan3::align_pairwise(std::tie(seq1, seq2), config))
{
Expand Down
14 changes: 7 additions & 7 deletions include/seqan3/alignment/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
* | **Config** | **0** | **1** | **2** | **3** | **4** | **5** | **6** | **7** | **8** | **9** |
* | --------------------------------------------------------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
* | \ref seqan3::align_cfg::aligned_ends "0: Aligned ends" | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
* | \ref seqan3::align_cfg::band "1: Band" | | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
* | \ref seqan3::align_cfg::band_fixed_size "1: Band" | | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
* | \ref seqan3::align_cfg::gap "2: Gap scheme" | | | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
* | \ref seqan3::global_alignment "3: Global alignment" | | | | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
* | \ref seqan3::local_alignment "4: Local alignment" | | | | | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
Expand Down Expand Up @@ -171,12 +171,12 @@
*
* SeqAn offers the computation of banded alignments to reduce the running time of the algorithm. This can be
* helpful if the region in which the optimal alignment exists is known a priori. To specify the banded alignment
* the developer can use the seqan3::align_cfg::band option initialised with a seqan3::static_band.
* The seqan3::static_band is constructed with a lower bound and an upper bound. The upper bound must always be greater
* than or equal to the lower bound. To position the band, imagine a rectangle where the first sequence is written on
* top and the second sequence along the left vertical side. A negative bound implies a start of the band within the
* vertical part while a positive bound implies a start within the top part of this rectangle at the respective
* position.
* the developer can use the seqan3::align_cfg::band_fixed_size option.
* This band configuration is initialised with a seqan3::align_cfg::lower_diagonal and an
* seqan3::align_cfg::upper_diagonal. The upper diagonal must always be greater than or equal to the lower diagonal.
* To choose the correct band parameters, imagine a matrix with the first sequence written on top and the second sequence
* along the left vertical side. A negative value reflects a start of the diagonal within the vertical part while a
* positive value implies a start within the top part of this matrix at the respective position.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A figure with an example would be great here, we could add that as a documentation todo for later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might produce some pics for my thesis anyway. So then I can add this here.

*
* ## Global and local alignments
*
Expand Down
109 changes: 81 additions & 28 deletions include/seqan3/alignment/configuration/align_config_band.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,104 @@
#pragma once

#include <seqan3/alignment/configuration/detail.hpp>
#include <seqan3/alignment/band/static_band.hpp>
#include <seqan3/alignment/exception.hpp>
#include <seqan3/core/algorithm/pipeable_config_element.hpp>
#include <seqan3/core/detail/empty_type.hpp>
#include <seqan3/core/detail/strong_type.hpp>

namespace seqan3::align_cfg
{

/*!\brief Configuration element for setting the band.
/*!\brief A strong type representing the lower diagonal of the seqan3::align_cfg::band_fixed_size.
* \ingroup alignment_configuration
*/
struct lower_diagonal : public seqan3::detail::strong_type<int32_t, lower_diagonal>
{
//!\brief The type of the strong type base class.
using base_t = seqan3::detail::strong_type<int32_t, lower_diagonal>;
// Import the base class constructors
using base_t::base_t;
};

/*!\brief A strong type representing the upper diagonal of the seqan3::align_cfg::band_fixed_size.
* \ingroup alignment_configuration
*/
struct upper_diagonal : public seqan3::detail::strong_type<int32_t, upper_diagonal>
{
//!\brief The type of the strong type base class.
using base_t = seqan3::detail::strong_type<int32_t, upper_diagonal>;
// Import the base class constructors
using base_t::base_t;
};

/*!\brief Configuration element for setting a fixed size band.
* \ingroup alignment_configuration
*
* \tparam band_t The type of the band.
*
* \details
*
* Configures the banded alignment algorithm. Currently only seqan3::static_band is allowed as argument.
* If no band is configured for the alignment algorithm the full alignment matrix will be computed.
* Before executing the algorithm the band is tested for valid settings, e.g. that the upper bound is not smaller than
* the lower bound, or the band is not shifted out of the alignment matrix. If an invalid setting is detected, a
* seqan3::invalid_alignment_configuration exception will be thrown.
* Configures the banded alignment algorithm. Currently only a fixed size band is allowed.
* The band is given in form of a seqan3::align_cfg::lower_diagonal and a seqan3::align_cfg::upper_diagonal.
* A diagonal represents the cells in the alignment matrix that are not crossed by the alignment either downwards by
* the lower diagonal or rightwards by the upper diagonal. Thus any computed alignment will be inside the area defined
* by the lower and the upper diagonal.
*
* If this configuration is default constructed or not set during the algorithm configuration the full alignment
* matrix will be computed.
*
* During the construction of this configuration element or before the execution of the alignment algorithm the
* band configuration is validated. If the user provided an invalid band, e.g. the upper diagonal is smaller than
* the lower diagonal, the alignment matrix would be ill configured such that the requested alignment method cannot
* be computed (because the global alignment requires the first cell and the last cell of the matrix to be reachable),
* then a seqan3::invalid_alignment_configuration will be thrown.
*
* ### Example
*
* \include test/snippet/alignment/configuration/align_cfg_band_example.cpp
*/
template <typename band_t>
//!\cond
requires std::same_as<band_t, static_band>
//!\endcond
struct band : public pipeable_config_element<band<band_t>, band_t>
class band_fixed_size : public pipeable_config_element<band_fixed_size>
{
private:
//!\brief The base class type.
using base_t = pipeable_config_element<band_fixed_size>;

public:
//!\brief The selected lower diagonal. Defaults to `std::%numeric_limits<int32_t>::%lowest()`.
seqan3::align_cfg::lower_diagonal lower_diagonal{std::numeric_limits<int32_t>::lowest()};
//!\brief The selected upper diagonal. Defaults to `std::%numeric_limits<int32_t>::%max()`.
seqan3::align_cfg::upper_diagonal upper_diagonal{std::numeric_limits<int32_t>::max()};

/*!\name Constructor, destructor and assignment
* \{
*/
constexpr band_fixed_size() = default; //!< Defaulted.
constexpr band_fixed_size(band_fixed_size const &) = default; //!< Defaulted.
constexpr band_fixed_size(band_fixed_size &&) = default; //!< Defaulted.
constexpr band_fixed_size & operator=(band_fixed_size const &) = default; //!< Defaulted.
constexpr band_fixed_size & operator=(band_fixed_size &&) = default; //!< Defaulted.
smehringer marked this conversation as resolved.
Show resolved Hide resolved
~band_fixed_size() = default; //!< Defaulted.

/*!\brief Initialises the fixed size band by setting the lower and the upper matrix diagonal.
*
* \param lower_diagonal \copybrief seqan3::align_cfg::band_fixed_size::lower_diagonal
* \param upper_diagonal \copybrief seqan3::align_cfg::band_fixed_size::upper_diagonal
*
* \details
*
* The lower diagonal represents the lower bound of the banded matrix, i.e. the alignment cannot pass below this
* diagonal. Similar, the upper diagonal represents the upper bound of the alignment. During the alignment
* configuration and execution the band parameters will be checked and an exception will be thrown in case of
* an invalid configuration.
*/
constexpr band_fixed_size(seqan3::align_cfg::lower_diagonal const lower_diagonal,
seqan3::align_cfg::upper_diagonal const upper_diagonal) :
lower_diagonal{std::move(lower_diagonal)},
smehringer marked this conversation as resolved.
Show resolved Hide resolved
upper_diagonal{std::move(upper_diagonal)}
{}
//!\}

//!\privatesection
//!\brief Internal id to check for consistent configuration settings.
static constexpr detail::align_config_id id{detail::align_config_id::band};
};

/*!\name Type deduction guides
* \brief Deduces the template parameter from the argument.
* \relates seqan3::align_cfg::band
* \{
*/
/*!
* \brief Deduces the underlying band type.
* \tparam band_t The underlying type of the band.
*/
template <typename band_t>
band(band_t) -> band<band_t>;
//!\}

} // namespace seqan3::detail
} // namespace seqan3::align_cfg
2 changes: 1 addition & 1 deletion include/seqan3/alignment/configuration/detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ enum struct align_config_id : uint8_t
//!\brief ID for the \ref seqan3::align_cfg::alignment_result_capture "alignment_result_capture" option.
alignment_result_capture,
aligned_ends, //!< ID for the \ref seqan3::align_cfg::aligned_ends "aligned_ends" option.
band, //!< ID for the \ref seqan3::align_cfg::band "band" option.
band, //!< ID for the \ref seqan3::align_cfg::band_fixed_size "band" option.
debug, //!< ID for the \ref seqan3::align_cfg::debug "debug" option.
gap, //!< ID for the \ref seqan3::align_cfg::gap "gap" option.
global, //!< ID for the \ref seqan3::global_alignment "global alignment" option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <vector>

#include <seqan3/alignment/aligned_sequence/aligned_sequence_concept.hpp>
#include <seqan3/alignment/band/static_band.hpp>
#include <seqan3/alignment/matrix/detail/matrix_coordinate.hpp>
#include <seqan3/alignment/matrix/trace_directions.hpp>
#include <seqan3/alphabet/gap/gapped.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#pragma once

#include <seqan3/alignment/band/static_band.hpp>
#include <seqan3/alignment/configuration/align_config_band.hpp>
#include <seqan3/alignment/matrix/detail/alignment_matrix_column_major_range_base.hpp>
#include <seqan3/alignment/matrix/detail/alignment_score_matrix_one_column_base.hpp>
#include <seqan3/alignment/matrix/detail/alignment_score_matrix_proxy.hpp>
Expand Down Expand Up @@ -99,7 +99,7 @@ class alignment_score_matrix_one_column_banded :
*
* \param[in] first The first range.
* \param[in] second The second range.
* \param[in] band The seqan3::static_band in which to calculate the alignment.
* \param[in] band The seqan3::align_cfg::band_fixed_size in which to calculate the alignment.
* \param[in] initial_value The value to initialise the matrix with. Default initialised if not specified.
*
* \details
Expand All @@ -111,14 +111,14 @@ class alignment_score_matrix_one_column_banded :
std::ranges::forward_range second_sequence_t>
constexpr alignment_score_matrix_one_column_banded(first_sequence_t && first,
second_sequence_t && second,
static_band const & band,
align_cfg::band_fixed_size const & band,
score_t const initial_value = score_t{})
{
matrix_base_t::num_cols = static_cast<size_type>(std::ranges::distance(first) + 1);
matrix_base_t::num_rows = static_cast<size_type>(std::ranges::distance(second) + 1);

band_col_index = std::min<int32_t>(std::max<int32_t>(band.upper_bound, 0), matrix_base_t::num_cols - 1);
band_row_index = std::min<int32_t>(std::abs(std::min<int32_t>(band.lower_bound, 0)),
band_col_index = std::min<int32_t>(std::max<int32_t>(band.upper_diagonal.get(), 0), matrix_base_t::num_cols - 1);
band_row_index = std::min<int32_t>(std::abs(std::min<int32_t>(band.lower_diagonal.get(), 0)),
matrix_base_t::num_rows - 1);

band_size = band_col_index + band_row_index + 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#pragma once

#include <seqan3/alignment/band/static_band.hpp>
#include <seqan3/alignment/configuration/align_config_band.hpp>
#include <seqan3/alignment/matrix/detail/alignment_matrix_column_major_range_base.hpp>
#include <seqan3/alignment/matrix/detail/alignment_trace_matrix_base.hpp>
#include <seqan3/alignment/matrix/detail/alignment_trace_matrix_proxy.hpp>
Expand Down Expand Up @@ -115,7 +115,7 @@ class alignment_trace_matrix_full_banded :
*
* \param[in] first The first range.
* \param[in] second The second range.
* \param[in] band The seqan3::static_band in which to calculate the alignment.
* \param[in] band The seqan3::align_cfg::band_fixed_size in which to calculate the alignment.
* \param[in] initial_value The value to initialise the matrix with. Default initialised if not specified.
*
* \details
Expand All @@ -127,14 +127,16 @@ class alignment_trace_matrix_full_banded :
template <std::ranges::forward_range first_sequence_t, std::ranges::forward_range second_sequence_t>
constexpr alignment_trace_matrix_full_banded(first_sequence_t && first,
second_sequence_t && second,
static_band const & band,
align_cfg::band_fixed_size const & band,
[[maybe_unused]] trace_t const initial_value = trace_t{})
{
matrix_base_t::num_cols = static_cast<size_type>(std::ranges::distance(first) + 1);
matrix_base_t::num_rows = static_cast<size_type>(std::ranges::distance(second) + 1);

band_col_index = std::min<int32_t>(std::max<int32_t>(band.upper_bound, 0), matrix_base_t::num_cols - 1);
band_row_index = std::min<int32_t>(std::abs(std::min<int32_t>(band.lower_bound, 0)), matrix_base_t::num_rows - 1);
band_col_index = std::min<int32_t>(std::max<int32_t>(band.upper_diagonal.get(), 0),
matrix_base_t::num_cols - 1);
band_row_index = std::min<int32_t>(std::abs(std::min<int32_t>(band.lower_diagonal.get(), 0)),
matrix_base_t::num_rows - 1);
band_size = band_col_index + band_row_index + 1;

// Reserve one more cell to deal with last cell in the banded column which needs only the diagonal and up cell.
Expand Down
Loading