HIBF 1.0.0-rc.1
Loading...
Searching...
No Matches
layout.hpp
1// SPDX-FileCopyrightText: 2006-2026, Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2026, Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
5#pragma once
6
7#include <array> // for array
8#include <concepts> // for derived_from
9#include <cstddef> // for size_t
10#include <cstdint> // for uint8_t
11#include <format> // for formatter, format_error, format_to, format
12#include <functional> // for function
13#include <iosfwd> // for ostream, istream
14#include <optional> // for optional
15#include <string> // for string
16#include <string_view> // for string_view
17#include <vector> // for operator==, vector
18
19#include <hibf/layout/prefixes.hpp> // for layout_fullest_technical_bin_idx, layout_header, layout_lower_level
20#include <hibf/platform.hpp>
21
22namespace seqan::hibf
23{
24
25struct config;
26
27} // namespace seqan::hibf
28
29namespace seqan::hibf::layout
30{
31
35struct layout
36{
37 struct max_bin
38 {
39 std::vector<size_t> previous_TB_indices{}; // identifies the IBF based on upper levels
40 size_t id{}; // the technical bin id that has the maximum kmer content
41
42 friend auto operator<=>(max_bin const &, max_bin const &) = default;
43
44 // needs a template (instead of using std::ostream directly) to be able to only include <iosfwd>
45 template <typename stream_type>
47 friend stream_type & operator<<(stream_type & stream, max_bin const & object)
48 {
49 stream << prefix::layout_header << prefix::layout_lower_level << '_';
50 auto it = object.previous_TB_indices.begin();
51 auto end = object.previous_TB_indices.end();
52 // If not empty, we join with ';'
53 if (it != end)
54 {
55 stream << *it;
56 while (++it != end)
57 stream << ';' << *it;
58 }
59 stream << " " << prefix::layout_fullest_technical_bin_idx << object.id;
60
61 return stream;
62 }
63 };
64
65 struct user_bin
66 {
67 std::vector<size_t> previous_TB_indices{}; // previous technical bin indices which refer to merged bin indices.
68 size_t storage_TB_id{}; // id of the technical bin that the user bin is actuallly stored in
69 size_t number_of_technical_bins{}; // 1 == single bin, >1 == split_bin
70 size_t idx{}; // The index of the user bin corresponding to the order in data
71
72 friend auto operator<=>(user_bin const &, user_bin const &) = default;
73
74 // needs a template (instead of using std::ostream directly) to be able to only include <iosfwd>
75 template <typename stream_type>
77 friend stream_type & operator<<(stream_type & stream, user_bin const & object)
78 {
79 stream << object.idx << '\t';
80 for (auto bin : object.previous_TB_indices)
81 stream << bin << ';';
82 stream << object.storage_TB_id << '\t';
83 for ([[maybe_unused]] auto && elem : object.previous_TB_indices) // number of bins per merged level is 1
84 stream << "1;";
85 stream << object.number_of_technical_bins;
86
87 return stream;
88 }
89 };
90
91 void read_from(std::istream & stream);
92 void write_to(std::ostream & stream) const;
93
94 void clear();
95
101 [[nodiscard]] size_t number_of_levels() const;
102
112 {
114 enum class severity : uint8_t
115 {
116 note,
117 warning,
118 error
119 };
120
145
153
155 // needs a template (instead of using std::ostream directly) to be able to only include <iosfwd>
156 // `diagnostic_t` is always `diagnostic`. As a template parameter, it defers the check of the format string
157 // until std::formatter<diagnostic>, which can only be specialised after this class, is known.
158 template <typename stream_type, std::same_as<diagnostic> diagnostic_t>
160 friend stream_type & operator<<(stream_type & stream, diagnostic_t const & object)
161 {
162 stream << std::format("{}", object);
163 return stream;
164 }
165 };
166
198
205 static void throw_on_error(diagnostic const & finding);
206
228 bool validate(config const & config, diagnostic_handler const & handler = throw_on_error) const;
230
231 size_t top_level_max_bin_id{};
232 std::vector<max_bin> max_bins{};
233 std::vector<user_bin> user_bins{};
234
235 bool operator==(layout const &) const = default;
236};
237
238} // namespace seqan::hibf::layout
239
241template <>
242struct std::formatter<seqan::hibf::layout::layout::diagnostic>
243{
244 constexpr formatter() = default;
245 constexpr formatter(formatter const &) = default;
246 constexpr formatter & operator=(formatter const &) = default;
247 constexpr formatter(formatter &&) = default;
248 constexpr formatter & operator=(formatter &&) = default;
249 constexpr ~formatter() = default;
250
254 template <typename parse_context_t>
255 constexpr auto parse(parse_context_t & context)
256 {
257 auto const it = context.begin();
258 if (it != context.end() && *it != '}')
259 throw std::format_error{"seqan::hibf::layout::layout::diagnostic does not support format specifications."};
260 return it;
261 }
262
266 template <typename format_context_t>
268 {
270 if (diagnostic.level > severity::error)
271 throw std::format_error{"Invalid seqan::hibf::layout::layout::diagnostic::severity."};
272
273 constexpr std::array<std::string_view, 3> names{"NOTE", "WARNING", "ERROR"};
274 return std::format_to(context.out(),
275 "[HIBF LAYOUT {}] {}",
276 names[static_cast<size_t>(diagnostic.level)],
277 diagnostic.message);
278 }
279};
T begin(T... args)
T format(T... args)
T format_to(T... args)
T is_base_of_v
Provides platform and dependency checks.
The configuration used to build an (H)IBF.
Definition config.hpp:76
A finding of seqan::hibf::layout::layout::validate.
Definition layout.hpp:112
code
The kind of finding. The errors are listed roughly in the order the checks are run.
Definition layout.hpp:123
@ user_bin_out_of_range
A user bin index is not below config.number_of_user_bins.
@ duplicate_max_bin
max_bins contains more than one entry for an IBF.
@ invalid_max_bin
A max bin is neither a merged bin nor a user bin's first technical bin.
@ empty_technical_bins
An IBF has empty technical bins between its used technical bins.
@ empty_layout
The layout contains no user bins.
@ missing_user_bin
A user bin index is missing from the layout.
@ unexpected_empty_bins
An IBF does not end with the empty TBs config.empty_bin_fraction implies.
@ overlapping_technical_bins
Within an IBF, a technical bin is used more than once.
@ missing_max_bin
max_bins contains no entry for a lower-level IBF.
@ technical_bin_overflow
An IBF would have more than 2^64 - 64 technical bins.
@ technical_bin_exceeds_tmax
An IBF, with its empty bins, exceeds next_multiple_of_64(tmax) TBs.
@ max_bin_without_ibf
max_bins contains an entry for an IBF that does not exist.
@ top_level_max_bin_entry
max_bins contains an entry for the top-level IBF.
@ max_bin_exceeds_root
A max bin spans more than next_multiple_of_64(#TBs of the Root-IBF) TBs.
@ no_technical_bins
A user bin occupies zero technical bins.
@ single_bin_ibf
A lower-level IBF only contains a single user bin or merged bin.
@ duplicate_user_bin
A user bin index occurs more than once.
code what
Definition layout.hpp:147
std::optional< size_t > technical_bin
The affected technical bin of ibf, if any.
Definition layout.hpp:151
severity
How grave a finding is.
Definition layout.hpp:115
std::optional< std::vector< size_t > > ibf
The merged bins on the path to the affected IBF, empty for the Root-IBF. std::nullopt: no IBF.
Definition layout.hpp:149
friend stream_type & operator<<(stream_type &stream, diagnostic_t const &object)
Prints [HIBF LAYOUT <SEVERITY>] <message>, like std::format("{}", object).
Definition layout.hpp:160
std::string message
A human-readable description.
Definition layout.hpp:152
severity level
How grave the finding is.
Definition layout.hpp:146
Definition layout.hpp:38
The layout.
Definition layout.hpp:36
static void throw_on_error(diagnostic const &finding)
The default diagnostic handler of seqan::hibf::layout::layout::validate.
size_t number_of_levels() const
Returns the number of levels of the described HIBF.
bool validate(config const &config, diagnostic_handler const &handler=throw_on_error) const
Checks whether the layout describes a consistent HIBF for the given configuration.
auto format(seqan::hibf::layout::layout::diagnostic const &diagnostic, format_context_t &context) const
Writes [HIBF LAYOUT <SEVERITY>] <message>.
Definition layout.hpp:267
constexpr auto parse(parse_context_t &context)
Accepts only an empty format specification, e.g., "{}" or "{:}".
Definition layout.hpp:255
constexpr formatter(formatter const &)=default
Defaulted.
constexpr formatter & operator=(formatter &&)=default
Defaulted.
constexpr formatter & operator=(formatter const &)=default
Defaulted.
constexpr formatter(formatter &&)=default
Defaulted.