SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
search.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <seqan3/std/algorithm>
16 #include <seqan3/std/ranges>
17 
28 
29 namespace seqan3::detail
30 {
34 struct search_configuration_validator
35 {
40  template <typename query_t>
41  static void validate_query_type()
42  {
43  using pure_query_t = std::remove_cvref_t<query_t>;
44  if constexpr(range_dimension_v<pure_query_t> == 1u)
45  {
46  static_assert(std::ranges::random_access_range<pure_query_t>,
47  "The query sequence must model random_access_range.");
48  static_assert(std::ranges::sized_range<pure_query_t>, "The query sequence must model sized_range.");
49  }
50  else
51  {
52  static_assert(std::ranges::forward_range<pure_query_t>, "The query collection must model forward_range.");
53  static_assert(std::ranges::sized_range<pure_query_t>, "The query collection must model sized_range.");
54  static_assert(std::ranges::random_access_range<std::ranges::range_value_t<pure_query_t>>,
55  "Elements of the query collection must model random_access_range.");
56  static_assert(std::ranges::sized_range<std::ranges::range_value_t<pure_query_t>>,
57  "Elements of the query collection must model sized_range.");
58  }
59  }
60 };
61 } // namespace seqan3::detail
62 
63 namespace seqan3
64 {
65 
99 template <fm_index_specialisation index_t,
100  std::ranges::forward_range queries_t,
101  typename configuration_t = decltype(search_cfg::default_configuration)>
103  requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
105 inline auto search(queries_t && queries,
106  index_t const & index,
107  configuration_t const & cfg = search_cfg::default_configuration)
108 {
109  auto updated_cfg = detail::search_configurator::add_defaults(cfg);
110 
111  detail::search_configuration_validator::validate_query_type<queries_t>();
112 
113  size_t queries_size = std::ranges::distance(queries);
114  auto indexed_queries = views::zip(std::views::iota(size_t{0}, queries_size), queries);
115 
116  using indexed_queries_t = decltype(indexed_queries);
117 
118  using query_t = std::ranges::range_reference_t<indexed_queries_t>;
119  auto [algorithm, complete_config] = detail::search_configurator::configure_algorithm<query_t>(updated_cfg, index);
120 
121  using complete_configuration_t = decltype(complete_config);
122  using traits_t = detail::search_traits<complete_configuration_t>;
123  using algorithm_result_t = typename traits_t::search_result_type;
124  using execution_handler_t = std::conditional_t<
125  complete_configuration_t::template exists<search_cfg::parallel>(),
126  detail::execution_handler_parallel,
127  detail::execution_handler_sequential>;
128 
129  // Select the execution handler for the search configuration.
130  auto select_execution_handler = [&] ()
131  {
132  if constexpr (std::same_as<execution_handler_t, detail::execution_handler_parallel>)
133  {
134  auto thread_count = get<search_cfg::parallel>(complete_config).thread_count;
135  if (!thread_count)
136  throw std::runtime_error{"You must configure the number of threads in seqan3::search_cfg::parallel."};
137 
138  return execution_handler_t{*thread_count};
139  }
140  else
141  {
142  return execution_handler_t{};
143  }
144  };
145 
146  // Finally, choose between two way execution returning an algorithm range or calling a user callback on every hit.
147  if constexpr (traits_t::has_user_callback)
148  {
149  select_execution_handler().bulk_execute(algorithm,
150  indexed_queries,
151  get<search_cfg::on_result>(complete_config).callback);
152  }
153  else
154  {
155  using executor_t = detail::algorithm_executor_blocking<indexed_queries_t,
156  decltype(algorithm),
157  algorithm_result_t,
158  execution_handler_t>;
159 
160  return algorithm_result_generator_range{executor_t{std::move(indexed_queries),
161  std::move(algorithm),
162  algorithm_result_t{},
163  select_execution_handler()}};
164  }
165 }
166 
168 // Overload for a single query (not a collection of queries)
170 template <fm_index_specialisation index_t,
171  std::ranges::forward_range query_t,
172  typename configuration_t = decltype(search_cfg::default_configuration)>
173 inline auto search(query_t && query,
174  index_t const & index,
175  configuration_t const & cfg = search_cfg::default_configuration)
176 {
177  return search(std::views::single(std::forward<query_t>(query)), index, cfg);
178 }
179 
181 template <fm_index_specialisation index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
182 inline auto search(char const * const queries,
183  index_t const & index,
184  configuration_t const & cfg = search_cfg::default_configuration)
185 {
186  return search(std::string_view{queries}, index, cfg);
187 }
188 
190 template <fm_index_specialisation index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
191 inline auto search(std::initializer_list<char const * const> const & queries,
192  index_t const & index,
193  configuration_t const & cfg = search_cfg::default_configuration)
194 {
196  query.reserve(std::ranges::size(queries));
197  std::ranges::for_each(queries, [&query] (char const * const q) { query.push_back(std::string_view{q}); });
198  return search(std::move(query) | views::persist, index, cfg);
199 }
201 
203 
204 } // namespace seqan3
seqan3::single
@ single
The text is a single range.
Definition: concept.hpp:84
zip.hpp
Provides seqan3::views::zip.
search_configurator.hpp
Provides seqan3::detail::search_configurator.
std::string_view
std::vector::reserve
T reserve(T... args)
parallel.hpp
Provides seqan3::search_cfg::parallel configuration.
std::vector
configuration.hpp
Provides seqan3::detail::configuration and utility functions.
on_result.hpp
Provides seqan3::search_cfg::on_result.
algorithm
Adaptations of algorithms from the Ranges TS.
algorithm_result_generator_range.hpp
Provides seqan3::detail::algorithm_result_generator_range.
seqan3::views::persist
constexpr auto persist
A view adaptor that wraps rvalue references of non-views.
Definition: persist.hpp:233
std::vector::push_back
T push_back(T... args)
seqan3::views::move
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
algorithm_executor_blocking.hpp
Provides seqan3::detail::algorithm_executor_blocking.
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
persist.hpp
Provides seqan3::views::persist.
std::runtime_error
seqan3::pack_traits::size
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:116
ranges
Adaptations of concepts from the Ranges TS.
std::remove_cvref_t
search_traits.hpp
Provides seqan3::detail::search_traits.
default_configuration.hpp
Provides the default configuration for the seqan3::search() interface.
std::conditional_t
fm_index_specialisation
Concept for unidirectional FM indices.
seqan3::search
auto search(queries_t &&queries, index_t const &index, configuration_t const &cfg=search_cfg::default_configuration)
Search a query or a range of queries in an index.
Definition: search.hpp:105
seqan3::search_cfg::default_configuration
const configuration default_configuration
The default configuration: Compute all exact matches.
Definition: default_configuration.hpp:32
std::initializer_list
seqan3::algorithm_result_generator_range
An input range over the algorithm results generated by the underlying algorithm executor.
Definition: algorithm_result_generator_range.hpp:44