Skip to content

Commit

Permalink
[FEATURE] Make search modi into individual pipeable config elements.
Browse files Browse the repository at this point in the history
  • Loading branch information
smehringer committed May 14, 2020
1 parent d87d694 commit 14bb7ae
Show file tree
Hide file tree
Showing 21 changed files with 205 additions and 120 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ Note that 3.1.0 will be the first API stable release and interfaces in this rele
#### Search

* Moved `seqan3::search` from `search/algorithm/` to `search/` ([\#1696](https://github.com/seqan/seqan3/pull/1696)).
* Configuration refactoring:
* The names for the search mode configuration have changed and are now individual config elements
that are pipeable ([\#1639](https://github.com/seqan/seqan3/pull/1639)):
`seqan3::search_cfg::all` to `seqan3::search_cfg::hit_all`
`seqan3::search_cfg::best` to `seqan3::search_cfg::hit_single_best`
`seqan3::search_cfg::all_best` to `seqan3::search_cfg::hit_all_best`
`seqan3::search_cfg::strata{5}` to `seqan3::search_cfg::hit_strata{5}`

## Notable Bug-fixes

Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void map_reads(std::filesystem::path const & query_path,
seqan3::sequence_file_input query_in{query_path};

seqan3::configuration const search_config = seqan3::search_cfg::max_error{seqan3::search_cfg::total{errors}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all_best};
seqan3::search_cfg::hit_all_best;

for (auto & [query, id, qual] : query_in | seqan3::views::take(20))
{
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void map_reads(std::filesystem::path const & query_path,
seqan3::sequence_file_input query_in{query_path};

seqan3::configuration const search_config = seqan3::search_cfg::max_error{seqan3::search_cfg::total{errors}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all_best};
seqan3::search_cfg::hit_all_best;

//! [alignment_config]
seqan3::configuration const align_config = seqan3::align_cfg::edit |
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void map_reads(std::filesystem::path const & query_path,
//! [alignment_file_output]

seqan3::configuration const search_config = seqan3::search_cfg::max_error{seqan3::search_cfg::total{errors}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all_best};
seqan3::search_cfg::hit_all_best;

seqan3::configuration const align_config = seqan3::align_cfg::edit |
seqan3::align_cfg::aligned_ends{seqan3::free_ends_first} |
Expand Down
8 changes: 4 additions & 4 deletions doc/tutorial/search/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,10 @@ At position 85: ACT

Besides the error configuration, you can define what kind of hits should be reported:

- seqan3::search_cfg::all: Report all hits that satisfy the (approximate) search.
- seqan3::search_cfg::best: Report the best hit, i.e. the *first* hit with the lowest edit distance.
- seqan3::search_cfg::all_best: Report all hits with the lowest edit distance.
- seqan3::search_cfg::strata: best+x mode. Report all hits within the x-neighbourhood of the best hit.
- seqan3::search_cfg::hit_all: Report all hits that satisfy the (approximate) search.
- seqan3::search_cfg::hit_single_best: Report the best hit, i.e. the *first* hit with the lowest edit distance.
- seqan3::search_cfg::hit_all_best: Report all hits with the lowest edit distance.
- seqan3::search_cfg::hit_strata: best+x mode. Report all hits within the x-neighbourhood of the best hit.

The mode is appended to the error configuration by using the `|`-operator:
\snippet doc/tutorial/search/search_small_snippets.cpp mode_best
Expand Down
4 changes: 2 additions & 2 deletions doc/tutorial/search/search_small_snippets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ seqan3::configuration const cfg = seqan3::search_cfg::max_error{seqan3::search_c
seqan3::search_cfg::substitution{0},
seqan3::search_cfg::insertion{1},
seqan3::search_cfg::deletion{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::best};
seqan3::search_cfg::hit_single_best;
//![mode_best]
}

Expand All @@ -104,7 +104,7 @@ seqan3::configuration const cfg = seqan3::search_cfg::max_error{seqan3::search_c
seqan3::search_cfg::substitution{0},
seqan3::search_cfg::insertion{1},
seqan3::search_cfg::deletion{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::strata{2}};
seqan3::search_cfg::hit_strata{2};
//![mode_strata]
}

Expand Down
8 changes: 4 additions & 4 deletions doc/tutorial/search/search_solution4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,25 @@ int main()

seqan3::debug_stream << "Searching all hits\n";
seqan3::configuration const cfg_all = seqan3::search_cfg::max_error{seqan3::search_cfg::total{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all};
seqan3::search_cfg::hit_all;
auto results_all = search(query, index, cfg_all);
seqan3::debug_stream << "Hits: " << results_all << "\n";

seqan3::debug_stream << "Searching all best hits\n";
seqan3::configuration const cfg_all_best = seqan3::search_cfg::max_error{seqan3::search_cfg::total{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all_best};
seqan3::search_cfg::hit_all_best;
auto results_all_best = search(query, index, cfg_all_best);
seqan3::debug_stream << "Hits: " << results_all_best << "\n";

seqan3::debug_stream << "Searching best hit\n";
seqan3::configuration const cfg_best = seqan3::search_cfg::max_error{seqan3::search_cfg::total{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::best};
seqan3::search_cfg::hit_single_best;
auto results_best = search(query, index, cfg_best);
seqan3::debug_stream << "Hits " << results_best << "\n";

seqan3::debug_stream << "Searching all hits in the 1-stratum\n";
seqan3::configuration const cfg_strata = seqan3::search_cfg::max_error{seqan3::search_cfg::total{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::strata{1}};
seqan3::search_cfg::hit_strata{1};
auto results_strata = search(query, index, cfg_strata);
seqan3::debug_stream << "Hits: " << results_strata << "\n";
}
4 changes: 2 additions & 2 deletions doc/tutorial/search/search_solution5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void run_text_single()
seqan3::debug_stream << "Searching all best hits allowing for 1 error in a single text\n";

seqan3::configuration const search_config = seqan3::search_cfg::max_error{seqan3::search_cfg::total{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all_best};
seqan3::search_cfg::hit_all_best;
seqan3::configuration const align_config = seqan3::align_cfg::edit |
seqan3::align_cfg::aligned_ends{seqan3::free_ends_first} |
seqan3::align_cfg::result{seqan3::with_alignment};
Expand Down Expand Up @@ -54,7 +54,7 @@ void run_text_collection()
seqan3::debug_stream << "Searching all best hits allowing for 1 error in a text collection\n";

seqan3::configuration const search_config = seqan3::search_cfg::max_error{seqan3::search_cfg::total{1}} |
seqan3::search_cfg::mode{seqan3::search_cfg::all_best};
seqan3::search_cfg::hit_all_best;
seqan3::configuration const align_config = seqan3::align_cfg::edit |
seqan3::align_cfg::aligned_ends{seqan3::free_ends_first} |
seqan3::align_cfg::result{seqan3::with_alignment};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ namespace seqan3::search_cfg
*/
inline constexpr configuration default_configuration = max_error{total{0}, substitution{0}, insertion{0}, deletion{0}} |
output{text_position} |
mode{all};
hit_all;

} // namespace seqan3::search_cfg
128 changes: 70 additions & 58 deletions include/seqan3/search/configuration/mode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,97 +6,109 @@
// -----------------------------------------------------------------------------------------------------

/*!\file
* \brief Provides the mode configuration to define the search modes "all", "all_best", "best" and "strata".
* \brief Provides the mode configuration to define the search modes "hit_strata", "hit_all",
* "hit_all_best", "hit_single_best".
* \author Christopher Pockrandt <christopher.pockrandt AT fu-berlin.de>
* \author Rene Rahn <rene.rahn AT fu-berlin.de>
* \author Svenja Mehringer <svenja.mehringer AT fu-berlin.de>
*/

#pragma once

#include <seqan3/core/algorithm/configuration.hpp>
#include <variant>

#include <seqan3/core/algorithm/pipeable_config_element.hpp>
#include <seqan3/core/detail/strong_type.hpp>
#include <seqan3/core/type_traits/basic.hpp>
#include <seqan3/core/detail/empty_type.hpp>
#include <seqan3/core/detail/test_accessor.hpp>
#include <seqan3/core/type_list/traits.hpp>
#include <seqan3/core/type_traits/template_inspection.hpp>
#include <seqan3/search/configuration/detail.hpp>


namespace seqan3::detail
{

//!\brief Type for the "all" value for the configuration element "mode".
//!\ingroup search_configuration
struct search_mode_all {};
//!\brief Type for the "all_best" value for the configuration element "mode".
//!\ingroup search_configuration
struct search_mode_all_best {};
//!\brief Type for the "best" value for the configuration element "mode".
//!\ingroup search_configuration
struct search_mode_best {};

} // namespace seqan3::detail

namespace seqan3::search_cfg
/*!\brief Configuration element to receive all hits within the error bounds.
* \ingroup search_configuration
*/
struct hit_all_tag : public pipeable_config_element<hit_all_tag, empty_type>
{
//!\privatesection
//!\brief Internal id to check for consistent configuration settings.
static constexpr detail::search_config_id id{detail::search_config_id::mode};
};

//!\brief Configuration element to receive all hits within the error bounds.
//!\ingroup search_configuration
inline detail::search_mode_all constexpr all;
//!\brief Configuration element to receive all hits within the lowest number of errors.
//!\ingroup search_configuration
inline detail::search_mode_all_best constexpr all_best;
//!\brief Configuration element to receive one best hit (with the lowest number of errors).
//!\ingroup search_configuration
inline detail::search_mode_best constexpr best;

/*!\brief Configuration element to receive all hits with the best number of errors plus the strata value.
* A strong type of underlying type `uint8_t` that represents the number or errors for strata.
* All hits are found with the fewest number of errors plus 'value'.
/*!\brief Configuration element to receive all hits with the lowest number of errors within the bounds
* \ingroup search_configuration
* \tparam value_t The underlying type.
*/
struct strata : detail::strong_type<uint8_t, strata, detail::strong_type_skill::convert>
struct hit_all_best_tag : public pipeable_config_element<hit_all_best_tag, empty_type>
{
using detail::strong_type<uint8_t, strata, detail::strong_type_skill::convert>::strong_type;
//!\privatesection
//!\brief Internal id to check for consistent configuration settings.
static constexpr detail::search_config_id id{detail::search_config_id::mode};
};

/*!\brief Configuration element to determine the search mode.
* \ingroup search_configuration
*
*/
struct hit_single_best_tag : public pipeable_config_element<hit_single_best_tag, empty_type>
{
//!\privatesection
//!\brief Internal id to check for consistent configuration settings.
static constexpr detail::search_config_id id{detail::search_config_id::mode};
};

} // namespace seqan3::detail

namespace seqan3::search_cfg
{

/*!\brief Configuration element to receive all hits within the error bounds.
* \ingroup search_configuration
* \details
* This configuration element can be used to determine which hits are supported.
* Currently these modes are available:
* | Mode | Behaviour |
* |------------------------------|---------------------------------------------------------------------|
* | seqan3::search_cfg::all | Report all hits within error bounds. |
* | seqan3::search_cfg::all_best | Report all hits with the lowest number of errors within the bounds. |
* | seqan3::search_cfg::best | Report one best hit (hit with lowest error) within bounds. |
* | seqan3::search_cfg::strata | Report all hits within best + x errors. |
*
* | Mode | Behaviour |
* |---------------------------------------------|---------------------------------------------------------------------|
* | seqan3::search_cfg::hit_all | Report all hits within error bounds. |
* | seqan3::search_cfg::hit_all_best | Report all hits with the lowest number of errors within the bounds. |
* | seqan3::search_cfg::hit_single_best | Report one best hit (hit with lowest error) within bounds. |
* | seqan3::search_cfg::hit_strata | Report all hits within best + x errors. |
*
* The individual configuration elements to select a search mode cannot be combined with each other.
*
* ### Example
*
* \include test/snippet/search/configuration_modes.cpp
*
* \hideinitializer
*/
template <typename mode_t>
//!\cond
requires std::same_as<remove_cvref_t<mode_t>, detail::search_mode_all> ||
std::same_as<remove_cvref_t<mode_t>, detail::search_mode_all_best> ||
std::same_as<remove_cvref_t<mode_t>, detail::search_mode_best> ||
std::same_as<remove_cvref_t<mode_t>, strata>
//!\endcond
struct mode : public pipeable_config_element<mode<mode_t>, mode_t>
inline constexpr detail::hit_all_tag hit_all{};

/*!\brief Configuration element to receive all hits with the lowest number of errors within the bounds.
* \ingroup search_configuration
* \copydetails seqan3::search_cfg::hit_all
* \hideinitializer
*/
inline constexpr detail::hit_all_best_tag hit_all_best{};

/*!\brief Configuration element to receive one best hit (with the lowest number of errors).
* \ingroup search_configuration
* \copydetails seqan3::search_cfg::hit_all
* \hideinitializer
*/
inline constexpr detail::hit_single_best_tag hit_single_best{};

/*!\brief Configuration element to receive all hits with the best number of errors plus the strata value.
* All hits are found with the fewest number of errors plus 'stratum'.
* \ingroup search_configuration
* \copydetails seqan3::search_cfg::hit_all
*/
struct hit_strata : public pipeable_config_element<hit_strata, uint8_t>
{
//!\privatesection
//!\brief Internal id to check for consistent configuration settings.
static constexpr detail::search_config_id id{detail::search_config_id::mode};
};

/*!\name Type deduction guides
* \relates seqan3::search_cfg::mode
* \{
*/

//!\brief Deduces search mode type from constructor argument.
template <typename mode_t>
mode(mode_t) -> mode<remove_cvref_t<mode_t>>;
//!\}
} // namespace seqan3::search_cfg
2 changes: 1 addition & 1 deletion include/seqan3/search/detail/search_scheme_algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class search_scheme_algorithm : protected policies_t...
if (!internal_hits.empty())
{
internal_hits.clear(); // TODO:don't clear when using Optimum Search Schemes with lower error bounds
uint8_t const stratum = get<search_cfg::mode>(config).value;
uint8_t const stratum = get<search_cfg::hit_strata>(config).value;
error_state.total += stratum - 1;
search_algo_bi<false>(query, error_state, on_hit_delegate);
}
Expand Down
12 changes: 4 additions & 8 deletions include/seqan3/search/detail/search_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,13 @@ struct search_traits
static constexpr bool has_error_configuration = search_with_max_error | search_with_max_error_rate;

//!\brief A flag indicating whether search should find all hits.
static constexpr bool search_all_hits =
search_configuration_t::template exists<search_cfg::mode<detail::search_mode_all>>();
static constexpr bool search_all_hits = search_configuration_t::template exists<hit_all_tag>();
//!\brief A flag indicating whether search should find best hits.
static constexpr bool search_best_hits =
search_configuration_t::template exists<search_cfg::mode<detail::search_mode_best>>();
static constexpr bool search_best_hits = search_configuration_t::template exists<hit_single_best_tag>();
//!\brief A flag indicating whether search should find all best hits.
static constexpr bool search_all_best_hits =
search_configuration_t::template exists<search_cfg::mode<detail::search_mode_all_best>>();
static constexpr bool search_all_best_hits = search_configuration_t::template exists<hit_all_best_tag>();
//!\brief A flag indicating whether search should find strata hits.
static constexpr bool search_strata_hits =
search_configuration_t::template exists<search_cfg::mode<search_cfg::strata>>();
static constexpr bool search_strata_hits = search_configuration_t::template exists<search_cfg::hit_strata>();
//!\brief A flag indicating whether mode configuration was set in the search configuration.
static constexpr bool has_mode_configuration = search_all_hits |
search_best_hits |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class unidirectional_search_algorithm : protected policies_t...
if (!internal_hits.empty())
{
internal_hits.clear();
uint8_t const stratum = get<search_cfg::mode>(config).value;
uint8_t const stratum = get<search_cfg::hit_strata>(config).value;
error_state.total += stratum - 1;
search_trivial<false>(index_ptr->cursor(), query, 0, error_state, error_type::none);
}
Expand Down
6 changes: 3 additions & 3 deletions include/seqan3/search/search.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,20 @@ namespace seqan3::detail
*/
struct search_configurator
{
/*!\brief Add seqan3::search_cfg::all to the configuration if seqan3::search_cfg::mode was not set.
/*!\brief Add seqan3::search_cfg::hit_all to the configuration if seqan3::search_cfg::mode was not set.
* \tparam configuration_t The type of the search configuration.
* \param[in] cfg The configuration to be modified if necessary.
* \returns The configuration which is guaranteed to have a seqan3::search_cfg::mode available.
*
* \details
*
* If seqan3::search_cfg::mode was not set, it defaults to seqan3::search_cfg::all.
* If seqan3::search_cfg::mode was not set, it defaults to seqan3::search_cfg::hit_all.
*/
template <typename configuration_t>
static auto add_default_mode_configuration(configuration_t const & cfg)
{
if constexpr (!detail::search_traits<configuration_t>::has_mode_configuration)
return cfg | search_cfg::mode{search_cfg::all};
return cfg | search_cfg::hit_all;
else
return cfg;
}
Expand Down
Loading

0 comments on commit 14bb7ae

Please sign in to comment.