Skip to content
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
30 changes: 7 additions & 23 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1,29 +1,9 @@
# MIT License
#
# Copyright (c) 2026 Andrew Smith
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# SPDX-License-Identifier: MIT; Copyright 2026 Andrew D Smith
BasedOnStyle: LLVM
ColumnLimit: 80
IndentWidth: 2
AlwaysBreakAfterReturnType: All
BreakAfterReturnType: All
AlignAfterOpenBracket: true
ContinuationIndentWidth: 2
ConstructorInitializerIndentWidth: 2
BraceWrapping:
Expand All @@ -32,3 +12,7 @@ BraceWrapping:
BreakBeforeBraces: Custom
BreakConstructorInitializers: AfterColon
SpacesBeforeTrailingComments: 2
PackParameters:
BinPack: OnePerLine
BreakAfter: 0
AllowShortFunctionsOnASingleLine: All
19 changes: 12 additions & 7 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
Checks: "
concurrency-*,
cert-*,
cppcoreguidelines-*,
performance-*,
clang-diagnostic-*,
clang-analyzer-*,
modernize-*,
misc-*,
portability-*,
-misc-include-cleaner,
-misc-use-anonymous-namespace,
-misc-header-include-cycle,
-modernize-use-trailing-return-type,
-clang-diagnostic-unqualified-std-cast-call,
-clang-diagnostic-unknown-warning-option,
-clang-analyzer-unix.BlockInCriticalSection,
Expand All @@ -28,17 +36,14 @@ CheckOptions:
cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU'
cert-err33-c.AllowCastToVoid: 'true'
cert-err33-c.CheckedFunctions: '*'
cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false'
cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false'
cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables: 'true'
cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove: 'true'
cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues: '1;2;3;4;10'
cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues: '1.0;2.0;10.0;100.0'
google-readability-braces-around-statements.ShortStatementLines: '1'
google-readability-function-size.StatementThreshold: '800'
google-readability-namespace-comments.ShortNamespaceLines: '10'
google-readability-namespace-comments.SpacesBeforeComments: '2'
llvm-else-after-return.WarnOnConditionVariables: 'false'
llvm-else-after-return.WarnOnUnfixable: 'false'
llvm-qualified-auto.AddConstToQualified: 'false'
llvm-else-after-return.WarnOnConditionVariables: 'true'
llvm-else-after-return.WarnOnUnfixable: 'true'
llvm-qualified-auto.AddConstToQualified: 'true'
modernize-use-trailing-return-type.TransformLambdas: none
SystemHeaders: 'false'
6 changes: 4 additions & 2 deletions src/adapter_matcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ struct adapter_matcher {
get_grade(const std::uint64_t n_reads) const -> std::string;

[[nodiscard]] auto
report(const std::uint64_t n_reads, const std::uint64_t max_read_len,
report(const std::uint64_t n_reads,
const std::uint64_t max_read_len,
const base_group_vec &groups,
const file_grades &grades) const -> std::string;

[[nodiscard]] auto
html(const std::uint64_t n_reads, const std::uint64_t max_read_len,
html(const std::uint64_t n_reads,
const std::uint64_t max_read_len,
const base_group_vec &groups,
const file_grades &grades) const -> std::string;
};
Expand Down
59 changes: 30 additions & 29 deletions src/bam_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,31 @@
estimate_n_reads_bam(const std::string &filename)
-> std::tuple<std::uint64_t, std::uint64_t, std::int64_t> {
static constexpr auto max_n_reads = 128 * 1024;
std::unique_ptr<htsFile, int (*)(htsFile *)> f(
const std::unique_ptr<htsFile, int (*)(htsFile *)> in(
hts_open(std::data(filename), "r"), &hts_close);
if (!f)
if (!in)
throw std::system_error(std::make_error_code(std::errc(errno)),
"failed to open file: " + filename);
std::unique_ptr<sam_hdr_t, void (*)(sam_hdr_t *)> h(sam_hdr_read(f.get()),
&sam_hdr_destroy);
const std::unique_ptr<sam_hdr_t, void (*)(sam_hdr_t *)> h(
sam_hdr_read(in.get()), &sam_hdr_destroy);
if (!h)
throw std::system_error(std::make_error_code(std::errc(errno)),
"failed to read header: " + filename);

const auto format = hts_get_format(f.get());
const auto format = hts_get_format(in.get());
if (!format)
throw std::runtime_error("failed to identify file format: " + filename);

// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
const auto fp = format->format == bam ? f->fp.bgzf->fp : f->fp.hfile;
const auto fp = format->format == bam ? in->fp.bgzf->fp : in->fp.hfile;
const auto pos_after_header = htell(fp);
std::unique_ptr<bam1_t, void (*)(bam1_t *)> rec(bam_init1(), &bam_destroy1);
const std::unique_ptr<bam1_t, void (*)(bam1_t *)> rec(bam_init1(),
&bam_destroy1);
std::uint64_t n_reads{};
std::uint64_t total_read_len{};
int r{};
while (n_reads++ < max_n_reads &&
(r = sam_read1(f.get(), h.get(), rec.get())) >= 0)
(r = sam_read1(in.get(), h.get(), rec.get())) >= 0)
total_read_len += rec->core.l_qseq;
if (r < -1) // error
throw std::system_error(std::make_error_code(std::errc(errno)),
Expand All @@ -71,13 +72,13 @@ init_dups(const std::string &filename, const std::uint64_t n_unique)
return "TNGNNNCNNNNNNNNNNNNA"[x - 'A'];
};
static constexpr auto n_unique_multiplier = 10;
std::unique_ptr<htsFile, int (*)(htsFile *)> f(
const std::unique_ptr<htsFile, int (*)(htsFile *)> in(
hts_open(std::data(filename), "r"), &hts_close);
if (!f)
if (!in)
throw std::system_error(std::make_error_code(std::errc(errno)),
"failed to open file: " + filename);
std::unique_ptr<sam_hdr_t, void (*)(sam_hdr_t *)> h(sam_hdr_read(f.get()),
&sam_hdr_destroy);
const std::unique_ptr<sam_hdr_t, void (*)(sam_hdr_t *)> h(
sam_hdr_read(in.get()), &sam_hdr_destroy);
if (!h)
throw std::system_error(std::make_error_code(std::errc(errno)),
"failed to read header: " + filename);
Expand All @@ -90,7 +91,7 @@ init_dups(const std::string &filename, const std::uint64_t n_unique)
std::uint64_t n_reads{};
const auto max_n_reads = n_unique_multiplier * n_unique;
while (n_reads++ < max_n_reads && std::size(dups) < n_unique &&
(r = sam_read1(f.get(), h.get(), rec.get())) >= 0) {
(r = sam_read1(in.get(), h.get(), rec.get())) >= 0) {
const auto l_qseq = rec->core.l_qseq;
const auto seq = bam_get_seq(rec.get());
if (std::ssize(buffer) < l_qseq)
Expand All @@ -111,8 +112,8 @@ init_dups(const std::string &filename, const std::uint64_t n_unique)
}

auto
bam_file::load_next(const std::int32_t file_id, //
task_queue &tq, //
bam_file::load_next(const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void {
is_first_load = false;
if (output_cursor > 0) {
Expand All @@ -133,23 +134,23 @@ bam_file::load_next(const std::int32_t file_id, //
input_last = std::distance(std::data(input_buffer), in_itr);
}

[[nodiscard]] inline auto
partition(auto itr, //
const auto end, //
const std::int64_t n_chunks, //
const std::int32_t file_id, //
task_queue &tq, //
[[nodiscard]] static inline auto
partition(auto itr,
const auto end,
const std::int64_t n_chunks,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) {
// ADS: this isn't working as desired: the end position of each part should be
// the first record end past the 'end_itr' below unless end_itr == end
auto dist = std::distance(itr, end);
const auto chunk_size = (dist + n_chunks - 1) / n_chunks;
while (itr != end) {
dist = std::distance(itr, end);
auto end_itr = itr + (dist < chunk_size ? dist : chunk_size);
const auto end_itr = itr + (dist < chunk_size ? dist : chunk_size);
// ADS: find_end_pos doesn't find end pos of a record, but of a range, so
// includes multiple records
auto next_itr = bamrec::find_end_pos(itr, end_itr);
const auto next_itr = bamrec::find_end_pos(itr, end_itr);
if (next_itr == itr)
break;
++n_tasks;
Expand All @@ -160,9 +161,9 @@ partition(auto itr, //
}

auto
bam_file::get_chunks(const std::int64_t n_chunks, //
const std::int32_t file_id, //
task_queue &tq, //
bam_file::get_chunks(const std::int64_t n_chunks,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void {
// Swap so the input buffer can be used to inflate more data and the former
// input buffer has been inflated and will provide data for analysis
Expand All @@ -179,9 +180,9 @@ bam_file::get_chunks(const std::int64_t n_chunks, //
}

auto
bam_file::make_tasks(const std::int64_t n_threads, //
const std::int32_t file_id, //
task_queue &tq, //
bam_file::make_tasks(const std::int64_t n_threads,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void {
static constexpr auto n_chunks_per_thread = 8;
const auto n_chunks = n_chunks_per_thread * n_threads;
Expand Down
40 changes: 23 additions & 17 deletions src/bam_file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class bam_file {

public:
bam_file(const std::string &filename, const std::int64_t buf_size) :
input_buffer(get_input_buffer_size(buf_size) + min_buf_size), //
output_buffer(get_output_buffer_size(buf_size) + min_buf_size), //
br(filename, get_reader_buffer_size(buf_size)) //
input_buffer(get_input_buffer_size(buf_size) + min_buf_size),
output_buffer(get_output_buffer_size(buf_size) + min_buf_size),
br(filename, get_reader_buffer_size(buf_size)) //
{}

// clang-format off
Expand All @@ -71,10 +71,10 @@ class bam_file {
reset(bam_file &reads_file) -> void;

friend auto
make_tasks(bam_file &reads_file, //
const std::int64_t n_threads, //
const std::int32_t file_id, //
task_queue &tq, //
make_tasks(bam_file &reads_file,
const std::int64_t n_threads,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void;

private:
Expand All @@ -88,20 +88,26 @@ class bam_file {
}

auto
get_chunks(const std::int64_t n_chunks, const std::int32_t file_id,
task_queue &tq, std::atomic_int32_t &n_tasks) -> void;
get_chunks(const std::int64_t n_chunks,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void;

auto
load_next(const std::int32_t file_id, task_queue &tq,
load_next(const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void;

auto
make_tasks_inflate(const std::int32_t file_id, task_queue &tq,
make_tasks_inflate(const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void;

auto
make_tasks(const std::int64_t n_chunks, const std::int32_t file_id,
task_queue &tq, std::atomic_int32_t &n_tasks) -> void;
make_tasks(const std::int64_t n_chunks,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void;

[[nodiscard]] auto
inflate_only() const -> bool {
Expand All @@ -128,10 +134,10 @@ init_dups(const std::string &filename, const std::uint64_t n_unique)
-> dups_map_t;

inline auto
make_tasks(bam_file &reads_file, //
const std::int64_t n_threads, //
const std::int32_t file_id, //
task_queue &tq, //
make_tasks(bam_file &reads_file,
const std::int64_t n_threads,
const std::int32_t file_id,
task_queue &tq,
std::atomic_int32_t &n_tasks) -> void {
n_tasks = 1; // for current task, which makes tasks
if (!reads_file.inflate_only())
Expand Down
4 changes: 2 additions & 2 deletions src/bam_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#include <stdexcept>

[[nodiscard]] auto
bam_header::update(const_iterator itr,
const const_iterator end) -> const_iterator {
bam_header::update(const_iterator itr, const const_iterator end)
-> const_iterator {
static constexpr auto msg = "incorrect BAM magic identified: {} at {}";
const auto update_u32 = [](auto &val, const auto inc, const auto the_byte) {
// NOLINTNEXTLINE(*-avoid-magic-numbers)
Expand Down
12 changes: 8 additions & 4 deletions src/bam_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,14 @@ struct bam_header {
}
}

NLOHMANN_DEFINE_TYPE_INTRUSIVE(bam_header, magic_bytes_remaining,
l_text_bytes_remaining, l_text,
n_ref_bytes_remaining, n_ref,
l_name_bytes_remaining, name_bytes_remaining,
NLOHMANN_DEFINE_TYPE_INTRUSIVE(bam_header,
magic_bytes_remaining,
l_text_bytes_remaining,
l_text,
n_ref_bytes_remaining,
n_ref,
l_name_bytes_remaining,
name_bytes_remaining,
l_ref_bytes_remaining);
};

Expand Down
10 changes: 5 additions & 5 deletions src/bamrec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ assign_sequence(bidir_itr_t first, auto last, output_itr_t d_first) {
}

[[nodiscard]] auto
bamrec::get_next(bamrec::pos_t &itr, const bamrec::pos_t end,
bamrec &rec) -> bool {
bamrec::get_next(bamrec::pos_t &itr, const bamrec::pos_t end, bamrec &rec)
-> bool {
if (std::distance(itr, end) < bam_core_t::sz)
return false;
bam_core_t core{};
Expand All @@ -80,7 +80,7 @@ bamrec::get_next(bamrec::pos_t &itr, const bamrec::pos_t end,
auto out_itr = std::begin(rec.buffer);
std::copy_n(itr + bam_core_t::read_name_offset, rec.name_len, out_itr);
out_itr += rec.name_len; // increment data cursor to sequence
auto seq_in = itr + core.seq_offset();
const auto seq_in = itr + core.seq_offset();
if (core.bam_is_rev())
assign_sequence_revcomp(seq_in, core.l_seq, out_itr);
else
Expand All @@ -102,8 +102,8 @@ bamrec::get_next(bamrec::pos_t &itr, const bamrec::pos_t end,
}

[[nodiscard]] auto
bamrec::find_end_pos(bamrec::pos_t itr,
const bamrec::pos_t end) -> bamrec::pos_t {
bamrec::find_end_pos(bamrec::pos_t itr, const bamrec::pos_t end)
-> bamrec::pos_t {
static constexpr std::int64_t record_size_size = sizeof(std::uint32_t);
std::uint32_t record_size{};
while (itr != end) {
Expand Down
3 changes: 2 additions & 1 deletion src/base_groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ get_linear_interval(const std::uint64_t n_bases,
}

[[nodiscard]] auto
make_base_groups(const std::uint64_t n_bases, const std::uint64_t n_initial,
make_base_groups(const std::uint64_t n_bases,
const std::uint64_t n_initial,
const std::uint64_t n_groups_target) -> base_group_vec {
static constexpr auto make_one_group = [](const auto a, const auto b) {
return base_group_t{a, b};
Expand Down
3 changes: 2 additions & 1 deletion src/base_groups.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ using base_group_t = std::pair<std::uint64_t, std::uint64_t>;
using base_group_vec = std::vector<base_group_t>;

[[nodiscard]] auto
make_base_groups(const std::uint64_t n_bases, const std::uint64_t n_initial,
make_base_groups(const std::uint64_t n_bases,
const std::uint64_t n_initial,
const std::uint64_t n_groups_target) -> base_group_vec;

[[nodiscard]] auto
Expand Down
Loading
Loading