SeqAn3 3.3.0-rc.1
The Modern C++ library for sequence analysis.
 
Loading...
Searching...
No Matches
search.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2022, 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 <algorithm>
16#include <ranges>
17
30
31namespace seqan3::detail
32{
37{
42 template <typename query_t>
43 static void validate_query_type()
44 {
45 using pure_query_t = std::remove_cvref_t<query_t>;
46 if constexpr (range_dimension_v<pure_query_t> == 1u)
47 {
48 static_assert(std::ranges::random_access_range<pure_query_t>,
49 "The query sequence must model random_access_range.");
50 static_assert(std::ranges::sized_range<pure_query_t>, "The query sequence must model sized_range.");
51 }
52 else
53 {
54 static_assert(std::ranges::forward_range<pure_query_t>, "The query collection must model forward_range.");
55 static_assert(std::ranges::sized_range<pure_query_t>, "The query collection must model sized_range.");
56 static_assert(std::ranges::random_access_range<std::ranges::range_value_t<pure_query_t>>,
57 "Elements of the query collection must model random_access_range.");
58 static_assert(std::ranges::sized_range<std::ranges::range_value_t<pure_query_t>>,
59 "Elements of the query collection must model sized_range.");
60 }
61 }
62};
63} // namespace seqan3::detail
64
65namespace seqan3
66{
102template <typename index_t,
103 std::ranges::forward_range queries_t,
104 typename configuration_t = decltype(search_cfg::default_configuration)>
105 requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
106 && std::same_as<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>
107inline auto
108search(queries_t && queries, index_t const & index, configuration_t const & cfg = search_cfg::default_configuration)
109{
110 auto updated_cfg = detail::search_configurator::add_defaults(cfg);
111
112 detail::search_configuration_validator::validate_query_type<queries_t>();
113
114 size_t queries_size = std::ranges::distance(queries);
115 auto indexed_queries = views::zip(std::views::iota(size_t{0}, queries_size), std::forward<queries_t>(queries));
116
117 using indexed_queries_t = decltype(indexed_queries);
118
119 using query_t = std::ranges::range_reference_t<indexed_queries_t>;
120 auto [algorithm, complete_config] = detail::search_configurator::configure_algorithm<query_t>(updated_cfg, index);
121
122 using complete_configuration_t = decltype(complete_config);
124 using algorithm_result_t = typename traits_t::search_result_type;
128
129 // Select the execution handler for the search configuration.
130 auto select_execution_handler = [parallel = complete_config.get_or(search_cfg::parallel{})]()
131 {
132 if constexpr (std::same_as<execution_handler_t, detail::execution_handler_parallel>)
133 {
134 auto thread_count = parallel.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// Convert query sequence if it does not match the alphabet type of the index.
170template <typename index_t,
171 std::ranges::forward_range queries_t,
172 typename configuration_t = decltype(search_cfg::default_configuration)>
173 requires std::ranges::forward_range<std::ranges::range_reference_t<queries_t>>
174 && (!std::same_as<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>)
175inline auto search(queries_t && queries,
176 index_t const & index,
177 configuration_t const & cfg = search_cfg::default_configuration)
178{
179 static_assert(std::convertible_to<range_innermost_value_t<queries_t>, typename index_t::alphabet_type>,
180 "The alphabet of the text collection must be convertible to the alphabet of the index.");
181
182 if constexpr (range_dimension_v<queries_t> == 2u)
183 return search(queries | views::deep{views::convert<typename index_t::alphabet_type>}, index, cfg);
184 else
185 return search(queries | views::convert<typename index_t::alphabet_type>, index, cfg);
186}
187
188// Overload for a single query (not a collection of queries)
190template <typename index_t,
191 std::ranges::forward_range query_t,
192 typename configuration_t = decltype(search_cfg::default_configuration)>
193inline auto
194search(query_t && query, index_t const & index, configuration_t const & cfg = search_cfg::default_configuration)
195{
196 return search(std::views::single(std::forward<query_t>(query)), index, cfg);
197}
198
200template <typename index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
201inline auto search(char const * const queries,
202 index_t const & index,
203 configuration_t const & cfg = search_cfg::default_configuration)
204{
205 return search(std::string_view{queries}, index, cfg);
206}
207
209template <typename index_t, typename configuration_t = decltype(search_cfg::default_configuration)>
211 index_t const & index,
212 configuration_t const & cfg = search_cfg::default_configuration)
213{
215 query.reserve(std::ranges::size(queries));
216 std::ranges::for_each(queries,
217 [&query](char const * const q)
218 {
219 query.push_back(std::string_view{q});
220 });
221 return search(std::move(query) | seqan3::detail::all, index, cfg);
222}
224
225} // namespace seqan3
Provides seqan3::detail::algorithm_executor_blocking.
Provides seqan3::detail::algorithm_result_generator_range.
Provides seqan3::detail::all.
An input range over the algorithm results generated by the underlying algorithm executor.
Definition: algorithm_result_generator_range.hpp:48
A blocking algorithm executor for algorithms.
Definition: algorithm_executor_blocking.hpp:63
Handles the parallel execution of algorithms.
Definition: execution_handler_parallel.hpp:55
A global configuration type used to enable parallel execution of algorithms.
Definition: configuration_element_parallel_mode.hpp:32
static auto add_defaults(configuration_t const &cfg)
Adds default configurations if they were not set by the user.
Definition: search_configurator.hpp:136
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view.
Definition: deep.hpp:104
Provides seqan3::configuration and utility functions.
Provides seqan3::views::deep.
Provides the default configuration for the seqan3::search() interface.
T for_each(T... args)
constexpr auto all
Returns a view that includes all elements of the range argument.
Definition: all_view.hpp:204
constexpr configuration default_configuration
The default configuration: Compute all exact matches.
Definition: default_configuration.hpp:29
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:108
constexpr auto zip
A view adaptor that takes several views and returns tuple-like values from every i-th element of each...
Definition: zip.hpp:573
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
Provides seqan3::search_cfg::on_result.
Provides seqan3::search_cfg::parallel configuration.
T push_back(T... args)
T reserve(T... args)
Provides seqan3::detail::search_configurator.
Provides seqan3::detail::search_traits.
Handles the sequential execution of algorithms.
Definition: execution_handler_sequential.hpp:34
Class used to validate the search configuration.
Definition: search.hpp:37
static void validate_query_type()
Validates the query type to model std::ranges::random_access_range and std::ranges::sized_range.
Definition: search.hpp:43
A collection of traits extracted from the search configuration.
Definition: search_traits.hpp:34
Provides seqan3::views::convert.
Provides seqan3::views::zip.