From 7b09f2e6c7c35cf10a47e896bedf057fc222087e Mon Sep 17 00:00:00 2001 From: AndreaGuarracino Date: Thu, 15 Jun 2023 08:32:59 +0200 Subject: [PATCH 1/4] update WFA2-lib --- src/common/wflign/deps/WFA2-lib/.gitignore | 43 ++ .../wflign/deps/WFA2-lib/CMakeLists.txt | 20 +- src/common/wflign/deps/WFA2-lib/README.md | 10 +- .../deps/WFA2-lib/{VERSION => VERSION.txt} | 0 .../wflign/deps/WFA2-lib/alignment/cigar.c | 6 - .../wflign/deps/WFA2-lib/alignment/cigar.h | 3 - .../deps/WFA2-lib/alignment/score_matrix.c | 1 + .../deps/WFA2-lib/bindings/cpp/WFAligner.cpp | 89 ++-- .../deps/WFA2-lib/bindings/cpp/WFAligner.hpp | 34 +- .../deps/WFA2-lib/examples/wfa_lambda.cpp | 3 +- .../wflign/deps/WFA2-lib/img/wfa.endsfree.png | Bin 68149 -> 0 bytes .../deps/WFA2-lib/system/mm_allocator.c | 3 - .../wflign/deps/WFA2-lib/system/mm_stack.c | 2 - .../deps/WFA2-lib/system/profiler_counter.h | 3 - .../deps/WFA2-lib/system/profiler_timer.h | 1 - .../deps/WFA2-lib/tests/wfa.utest.cmp.sh | 29 +- .../tests/wfa.utest.performance.cmp.sh | 46 ++ .../WFA2-lib/tests/wfa.utest.performance.sh | 2 +- .../wflign/deps/WFA2-lib/tests/wfa.utest.sh | 32 +- .../tools/align_benchmark/align_benchmark.c | 40 +- .../align_benchmark/align_benchmark_params.c | 26 +- .../align_benchmark/align_benchmark_params.h | 14 +- .../benchmark/benchmark_edit.c | 12 +- .../benchmark/benchmark_gap_affine.c | 12 +- .../benchmark/benchmark_gap_affine2p.c | 12 +- .../benchmark/benchmark_gap_linear.c | 12 +- .../benchmark/benchmark_indel.c | 12 +- .../benchmark/benchmark_utils.c | 2 - .../benchmark/benchmark_utils.h | 2 - .../wflign/deps/WFA2-lib/utils/Makefile | 1 + .../wflign/deps/WFA2-lib/utils/commons.h | 1 + .../wflign/deps/WFA2-lib/utils/heatmap.h | 2 - .../deps/WFA2-lib/utils/string_padded.c | 140 +++++ .../string_padded.h} | 56 +- .../wflign/deps/WFA2-lib/utils/vector.h | 2 + .../wflign/deps/WFA2-lib/wavefront/Makefile | 4 - .../deps/WFA2-lib/wavefront/wavefront_align.c | 119 ++--- .../deps/WFA2-lib/wavefront/wavefront_align.h | 14 +- .../WFA2-lib/wavefront/wavefront_aligner.c | 266 +++------- .../WFA2-lib/wavefront/wavefront_attributes.c | 3 + .../WFA2-lib/wavefront/wavefront_attributes.h | 24 +- .../WFA2-lib/wavefront/wavefront_backtrace.c | 28 +- .../wavefront/wavefront_backtrace_buffer.c | 29 +- .../wavefront/wavefront_backtrace_buffer.h | 14 +- .../wavefront/wavefront_backtrace_offload.c | 1 + .../WFA2-lib/wavefront/wavefront_bialign.c | 288 ++++++----- .../WFA2-lib/wavefront/wavefront_bialign.h | 6 +- .../WFA2-lib/wavefront/wavefront_bialigner.c | 97 +--- .../WFA2-lib/wavefront/wavefront_bialigner.h | 40 +- .../WFA2-lib/wavefront/wavefront_compute.c | 7 +- .../wavefront/wavefront_compute_affine.c | 13 +- .../wavefront/wavefront_compute_affine2p.c | 12 +- .../wavefront/wavefront_compute_edit.c | 26 +- .../wavefront/wavefront_compute_linear.c | 13 +- .../deps/WFA2-lib/wavefront/wavefront_debug.c | 182 ++++--- .../deps/WFA2-lib/wavefront/wavefront_debug.h | 10 +- .../WFA2-lib/wavefront/wavefront_extend.c | 480 +++++++++++++----- .../WFA2-lib/wavefront/wavefront_extend.h | 14 +- .../wavefront/wavefront_extend_kernels.c | 177 ------- .../wavefront/wavefront_extend_kernels.h | 69 --- .../wavefront/wavefront_extend_kernels_avx.c | 35 -- .../wavefront/wavefront_extend_kernels_avx.h | 37 -- .../WFA2-lib/wavefront/wavefront_heuristic.c | 14 +- .../WFA2-lib/wavefront/wavefront_pcigar.c | 34 +- .../WFA2-lib/wavefront/wavefront_pcigar.h | 15 +- .../deps/WFA2-lib/wavefront/wavefront_plot.c | 27 +- .../WFA2-lib/wavefront/wavefront_sequences.c | 310 ----------- .../WFA2-lib/wavefront/wavefront_sequences.h | 148 ------ .../wavefront/wavefront_termination.c | 162 ------ .../WFA2-lib/wavefront/wavefront_unialign.c | 209 +++++++- .../WFA2-lib/wavefront/wavefront_unialign.h | 15 +- .../wflign/deps/WFA2-lib/wavefront/wfa.h | 52 +- src/common/wflign/src/wflign.cpp | 5 +- src/common/wflign/src/wflign_alignment.cpp | 1 + 74 files changed, 1578 insertions(+), 2095 deletions(-) create mode 100644 src/common/wflign/deps/WFA2-lib/.gitignore rename src/common/wflign/deps/WFA2-lib/{VERSION => VERSION.txt} (100%) delete mode 100644 src/common/wflign/deps/WFA2-lib/img/wfa.endsfree.png create mode 100755 src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh create mode 100644 src/common/wflign/deps/WFA2-lib/utils/string_padded.c rename src/common/wflign/deps/WFA2-lib/{wavefront/wavefront_termination.h => utils/string_padded.h} (57%) delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h delete mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c diff --git a/src/common/wflign/deps/WFA2-lib/.gitignore b/src/common/wflign/deps/WFA2-lib/.gitignore new file mode 100644 index 00000000..6148fb8a --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/.gitignore @@ -0,0 +1,43 @@ +lib/ +bin/ +build/ + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Test output files +tests/wfa.utest.log.correct +tests/wfa.utest.log.mem +tests/wfa.utest.log.time + + diff --git a/src/common/wflign/deps/WFA2-lib/CMakeLists.txt b/src/common/wflign/deps/WFA2-lib/CMakeLists.txt index f575ff94..07d68747 100644 --- a/src/common/wflign/deps/WFA2-lib/CMakeLists.txt +++ b/src/common/wflign/deps/WFA2-lib/CMakeLists.txt @@ -59,8 +59,8 @@ if (${CMAKE_BUILD_TYPE} MATCHES Release) endif() if ((${CMAKE_BUILD_TYPE} MATCHES Release) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo)) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS} ${OPTIMIZE_FLAGS}") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} ${OPTIMIZE_FLAGS}") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPTIMIZE_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPTIMIZE_FLAGS}") endif () if (${CMAKE_BUILD_TYPE} MATCHES "Debug") @@ -120,7 +120,6 @@ set(wfa2lib_SOURCE wavefront/wavefront_pcigar.c wavefront/wavefront_penalties.c wavefront/wavefront_plot.c - wavefront/wavefront_sequences.c wavefront/wavefront_slab.c wavefront/wavefront_unialign.c system/mm_stack.c @@ -133,6 +132,7 @@ set(wfa2lib_SOURCE utils/vector.c utils/commons.c utils/heatmap.c + utils/string_padded.c alignment/affine2p_penalties.c alignment/affine_penalties.c alignment/cigar.c @@ -150,6 +150,11 @@ target_include_directories(wfa2_static PUBLIC . wavefront utils) add_library(wfa2::wfa2 ALIAS wfa2) add_library(wfa2::wfa2_static ALIAS wfa2_static) +if(OPENMP) + target_link_libraries(wfa2_static PRIVATE OpenMP::OpenMP_C) + target_link_libraries(wfa2 PRIVATE OpenMP::OpenMP_C) +endif(OPENMP) + # ---- C++ binding library set(wfa2cpp_SOURCE @@ -163,13 +168,18 @@ add_library(wfa2cpp SHARED ${wfa2cpp_SOURCE}) set_target_properties(wfa2cpp PROPERTIES SOVERSION 0) set_target_properties(wfa2cpp_static PROPERTIES OUTPUT_NAME wfa2cpp) target_link_libraries(wfa2cpp PUBLIC wfa2) -target_link_libraries(wfa2cpp_static PUBLIC wfa2) +target_link_libraries(wfa2cpp_static PUBLIC wfa2_static) add_library(wfa2::wfa2cpp ALIAS wfa2cpp) add_library(wfa2::wfa2cpp_static ALIAS wfa2cpp_static) +if(OPENMP) + target_link_libraries(wfa2cpp_static PRIVATE OpenMP::OpenMP_CXX) + target_link_libraries(wfa2cpp PRIVATE OpenMP::OpenMP_CXX) +endif(OPENMP) + # ---- Get version -file (STRINGS "VERSION" BUILD_NUMBER) +file (STRINGS "VERSION.txt" BUILD_NUMBER) add_definitions(-DWFA2LIB_VERSION="${BUILD_NUMBER}") add_definitions(-DVERSION="${BUILD_NUMBER}") diff --git a/src/common/wflign/deps/WFA2-lib/README.md b/src/common/wflign/deps/WFA2-lib/README.md index 4d682e7e..6d05f53f 100644 --- a/src/common/wflign/deps/WFA2-lib/README.md +++ b/src/common/wflign/deps/WFA2-lib/README.md @@ -12,7 +12,7 @@ The wavefront alignment (WFA) algorithm is an **exact** gap-affine algorithm tha ### 1.2 What is WFA2-lib? -The WFA2 library implements the WFA algorithm for different distance metrics and alignment modes. It supports various [distance functions](#wfa2.distances): indel, edit, gap-lineal, gap-affine, and dual-gap gap-affine distances. The library allows computing only the score or the complete alignment (i.e., CIGAR) (see [Alignment Scope](#wfa2.scope)). Also, the WFA2 library supports computing end-to-end alignments (a.k.a. global-alignment) and ends-free alignments (including semi-global, glocal, and extension alignment) (see [Alignment Span](#wfa2.span)). In the case of long and noisy alignments, the library provides different [low-memory modes](#wfa2.mem) that significantly reduce the memory usage of the naive WFA algorithm implementation. Beyond the exact-alignment modes, the WFA2 library implements [heuristic modes](#wfa2.heuristics) that dramatically accelerate the alignment computation. Additionally, the library provides many other support functions to display and verify alignment results, control the overall memory usage, and more. +The WFA2 library implements the WFA algorithm for different distance metrics and alignment modes. It supports various [distance functions](#wfa2.distances): indel, edit, gap-linear, gap-affine, and dual-gap gap-affine distances. The library allows computing only the score or the complete alignment (i.e., CIGAR) (see [Alignment Scope](#wfa2.scope)). Also, the WFA2 library supports computing end-to-end alignments (a.k.a. global-alignment) and ends-free alignments (including semi-global, glocal, and extension alignment) (see [Alignment Span](#wfa2.span)). In the case of long and noisy alignments, the library provides different [low-memory modes](#wfa2.mem) that significantly reduce the memory usage of the naive WFA algorithm implementation. Beyond the exact-alignment modes, the WFA2 library implements [heuristic modes](#wfa2.heuristics) that dramatically accelerate the alignment computation. Additionally, the library provides many other support functions to display and verify alignment results, control the overall memory usage, and more. ### 1.3 Getting started @@ -21,7 +21,7 @@ Git clone and compile the library, tools, and examples. By default use cmake: ``` git clone https://github.com/smarco/WFA2-lib cd WFA2-lib -mkdir build +mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release cmake --build . --verbose ctest . --verbose @@ -173,7 +173,7 @@ An example of how to use them is [here](./bindings/rust/example.rs). ## 3. WFA2-LIB FEATURES * **Exact alignment** method that computes the optimal **alignment score** and/or **alignment CIGAR**. -* Supports **multiple distance metrics** (i.e., indel, edit, gap-lineal, gap-affine, and dual-gap gap-affine). +* Supports **multiple distance metrics** (i.e., indel, edit, gap-linear, gap-affine, and dual-gap gap-affine). * Allows performing **end-to-end** (a.k.a. global) and **ends-free** (e.g., semi-global, extension, overlap) alignment. * Implements **low-memory modes** to reduce and control memory consumption (down to `O(s)` using the `ultralow` mode). * Supports various **heuristic strategies** to use on top of the core WFA algorithm. @@ -592,6 +592,6 @@ Miquel Moretó has contributed with fruitful technical discussions and tireless ## 8. CITATION -**Santiago Marco-Sola, Juan Carlos Moure, Miquel Moreto, Antonio Espinosa**. ["Fast gap-affine pairwise alignment using the wavefront algorithm."](https://doi.org/10.1093/bioinformatics/btaa777). Bioinformatics, 2020. +**Santiago Marco-Sola, Juan Carlos Moure, Miquel Moreto, Antonio Espinosa**. ["Fast gap-affine pairwise alignment using the wavefront algorithm."](https://doi.org/10.1093/bioinformatics/btaa777) Bioinformatics, 2020. -**Santiago Marco-Sola, Jordan M Eizenga, Andrea Guarracino, Benedict Paten, Erik Garrison, Miquel Moreto**. ["Optimal gap-affine alignment in O(s) space"](https://doi.org/10.1093/bioinformatics/btad074). Bioinformatics, 2023. +**Santiago Marco-Sola, Jordan M Eizenga, Andrea Guarracino, Benedict Paten, Erik Garrison, Miquel Moreto**. Optimal gap-affine alignment in O(s) space. _bioRxiv_ (2022). DOI [2022.04.14.488380](https://doi.org/10.1101/2022.04.14.488380) diff --git a/src/common/wflign/deps/WFA2-lib/VERSION b/src/common/wflign/deps/WFA2-lib/VERSION.txt similarity index 100% rename from src/common/wflign/deps/WFA2-lib/VERSION rename to src/common/wflign/deps/WFA2-lib/VERSION.txt diff --git a/src/common/wflign/deps/WFA2-lib/alignment/cigar.c b/src/common/wflign/deps/WFA2-lib/alignment/cigar.c index 77b3c630..4c4efe39 100644 --- a/src/common/wflign/deps/WFA2-lib/alignment/cigar.c +++ b/src/common/wflign/deps/WFA2-lib/alignment/cigar.c @@ -226,10 +226,6 @@ int cigar_score_gap_affine2p( /* * Utils */ -bool cigar_is_null( - cigar_t* const cigar) { - return (cigar->begin_offset >= cigar->end_offset); -} int cigar_cmp( cigar_t* const cigar_a, cigar_t* const cigar_b) { @@ -511,5 +507,3 @@ void cigar_print_pretty( mm_allocator_free(mm_allocator,ops_alg); mm_allocator_free(mm_allocator,text_alg); } - - diff --git a/src/common/wflign/deps/WFA2-lib/alignment/cigar.h b/src/common/wflign/deps/WFA2-lib/alignment/cigar.h index 748e9244..fbc24ce5 100644 --- a/src/common/wflign/deps/WFA2-lib/alignment/cigar.h +++ b/src/common/wflign/deps/WFA2-lib/alignment/cigar.h @@ -96,9 +96,6 @@ int cigar_score_gap_affine2p( /* * Utils */ -bool cigar_is_null( - cigar_t* const cigar); - int cigar_cmp( cigar_t* const cigar_a, cigar_t* const cigar_b); diff --git a/src/common/wflign/deps/WFA2-lib/alignment/score_matrix.c b/src/common/wflign/deps/WFA2-lib/alignment/score_matrix.c index beae531e..c656a556 100644 --- a/src/common/wflign/deps/WFA2-lib/alignment/score_matrix.c +++ b/src/common/wflign/deps/WFA2-lib/alignment/score_matrix.c @@ -32,6 +32,7 @@ #include "utils/commons.h" #include "score_matrix.h" + /* * Setup */ diff --git a/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.cpp b/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.cpp index 8ca72c23..d2f4c826 100644 --- a/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.cpp +++ b/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.cpp @@ -64,6 +64,14 @@ WFAligner::~WFAligner() { /* * Align End-to-end */ +WFAligner::AlignmentStatus WFAligner::alignEnd2EndLambda( + const int patternLength, + const int textLength) { + // Configure + wavefront_aligner_set_alignment_end_to_end(wfAligner); + // Align (using custom matching function) + return (WFAligner::AlignmentStatus) wavefront_align(wfAligner,NULL,patternLength,NULL,textLength); +} WFAligner::AlignmentStatus WFAligner::alignEnd2End( const char* const pattern, const int patternLength, @@ -80,20 +88,23 @@ WFAligner::AlignmentStatus WFAligner::alignEnd2End( // Delegate return alignEnd2End(pattern.c_str(),pattern.length(),text.c_str(),text.length()); } -WFAligner::AlignmentStatus WFAligner::alignEnd2EndLambda( - int (*matchFunct)(int,int,void*), - void* matchFunctArguments, +/* + * Align Ends-free + */ +WFAligner::AlignmentStatus WFAligner::alignEndsFreeLambda( const int patternLength, - const int textLength) { + const int patternBeginFree, + const int patternEndFree, + const int textLength, + const int textBeginFree, + const int textEndFree) { // Configure - wavefront_aligner_set_alignment_end_to_end(wfAligner); + wavefront_aligner_set_alignment_free_ends(wfAligner, + patternBeginFree,patternEndFree, + textBeginFree,textEndFree); // Align (using custom matching function) - return (WFAligner::AlignmentStatus) - wavefront_align_lambda(wfAligner,matchFunct,matchFunctArguments,patternLength,textLength); + return (WFAligner::AlignmentStatus) wavefront_align(wfAligner,NULL,patternLength,NULL,textLength); } -/* - * Align Ends-free - */ WFAligner::AlignmentStatus WFAligner::alignEndsFree( const char* const pattern, const int patternLength, @@ -124,30 +135,13 @@ WFAligner::AlignmentStatus WFAligner::alignEndsFree( text.c_str(),text.length(), textBeginFree,textEndFree); } -WFAligner::AlignmentStatus WFAligner::alignEndsFreeLambda( - int (*matchFunct)(int,int,void*), - void* matchFunctArguments, - const int patternLength, - const int patternBeginFree, - const int patternEndFree, - const int textLength, - const int textBeginFree, - const int textEndFree) { - // Configure - wavefront_aligner_set_alignment_free_ends(wfAligner, - patternBeginFree,patternEndFree, - textBeginFree,textEndFree); - // Align (using custom matching function) - return (WFAligner::AlignmentStatus) - wavefront_align_lambda(wfAligner,matchFunct,matchFunctArguments,patternLength,textLength); -} -///* -// * Alignment resume -// */ -//WFAligner::AlignmentStatus WFAligner::alignResume() { -// // Resume alignment -// return (WFAligner::AlignmentStatus) wavefront_align_resume(wfAligner); -//} +/* + * Alignment resume + */ +WFAligner::AlignmentStatus WFAligner::alignResume() { + // Resume alignment + return (WFAligner::AlignmentStatus) wavefront_align_resume(wfAligner); +} /* * Heuristics */ @@ -195,6 +189,14 @@ void WFAligner::setHeuristicZDrop( wavefront_aligner_set_heuristic_zdrop( wfAligner,zdrop,steps_between_cutoffs); } +/* + * Custom extend-match function (lambda) + */ +void WFAligner::setMatchFunct( + int (*matchFunct)(int,int,void*), + void* matchFunctArguments) { + wavefront_aligner_set_match_funct(wfAligner,matchFunct,matchFunctArguments); +} /* * Limits */ @@ -210,12 +212,12 @@ void WFAligner::setMaxMemory( } // Parallelization void WFAligner::setMaxNumThreads( - const int maxNumThreads) { - wavefront_aligner_set_max_num_threads(wfAligner, maxNumThreads); + const int maxNumThreads) { + wavefront_aligner_set_max_num_threads(wfAligner, maxNumThreads); } void WFAligner::setMinOffsetsPerThread( - const int minOffsetsPerThread) { - wavefront_aligner_set_min_offsets_per_thread(wfAligner, minOffsetsPerThread); + const int minOffsetsPerThread) { + wavefront_aligner_set_min_offsets_per_thread(wfAligner, minOffsetsPerThread); } /* * Accessors @@ -247,14 +249,9 @@ char* WFAligner::strError( const int wfErrorCode) { return wavefront_align_strerror(wfErrorCode); } -void WFAligner::debugAddTag( - char* const debugTag) { - wfAligner->align_mode_tag = debugTag; - if (wfAligner->bialigner != NULL) { - wfAligner->bialigner->alg_forward->align_mode_tag = debugTag; - wfAligner->bialigner->alg_reverse->align_mode_tag = debugTag; - wfAligner->bialigner->alg_subsidiary->align_mode_tag = debugTag; - } +void WFAligner::setVerbose( + const int verbose) { + wfAligner->system.verbose = verbose; } /* * Indel Aligner (a.k.a Longest Common Subsequence - LCS) diff --git a/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp b/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp index 7aa26580..8da82bbc 100644 --- a/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp +++ b/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp @@ -65,6 +65,9 @@ class WFAligner { StatusOOM = WF_STATUS_OOM, }; // Align End-to-end + AlignmentStatus alignEnd2EndLambda( + const int patternLength, + const int textLength); AlignmentStatus alignEnd2End( const char* const pattern, const int patternLength, @@ -73,12 +76,14 @@ class WFAligner { AlignmentStatus alignEnd2End( std::string& pattern, std::string& text); - AlignmentStatus alignEnd2EndLambda( - int (*matchFunct)(int,int,void*), - void* matchFunctArguments, - const int patternLength, - const int textLength); // Align Ends-free + AlignmentStatus alignEndsFreeLambda( + const int patternLength, + const int patternBeginFree, + const int patternEndFree, + const int textLength, + const int textBeginFree, + const int textEndFree); AlignmentStatus alignEndsFree( const char* const pattern, const int patternLength, @@ -95,15 +100,8 @@ class WFAligner { std::string& text, const int textBeginFree, const int textEndFree); - AlignmentStatus alignEndsFreeLambda( - int (*matchFunct)(int,int,void*), - void* matchFunctArguments, - const int patternLength, - const int patternBeginFree, - const int patternEndFree, - const int textLength, - const int textBeginFree, - const int textEndFree); + // Alignment resume + AlignmentStatus alignResume(); // Heuristics void setHeuristicNone(); void setHeuristicBandedStatic( @@ -127,6 +125,10 @@ class WFAligner { void setHeuristicZDrop( const int zdrop, const int steps_between_cutoffs = 1); + // Custom extend-match function (lambda) + void setMatchFunct( + int (*matchFunct)(int,int,void*), + void* matchFunctArguments); // Limits void setMaxAlignmentScore( const int maxAlignmentScore); @@ -148,8 +150,8 @@ class WFAligner { // Misc char* strError( const int wfErrorCode); - void debugAddTag( - char* const debugTag); + void setVerbose( + const int verbose); protected: wavefront_aligner_attr_t attributes; wavefront_aligner_t* wfAligner; diff --git a/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp b/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp index d2e2fb7d..0fc60095 100644 --- a/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp +++ b/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp @@ -56,8 +56,9 @@ int match_function( int main(int argc,char* argv[]) { // Create a WFAligner WFAlignerGapAffine aligner(1,0,1,WFAligner::Alignment,WFAligner::MemoryHigh); + aligner.setMatchFunct(match_function,NULL); // Align - aligner.alignEnd2EndLambda(match_function,NULL,patternLength,textLength); + aligner.alignEnd2EndLambda(patternLength,textLength); cout << "WFA-Alignment returns score " << aligner.getAlignmentScore() << endl; // Print CIGAR diff --git a/src/common/wflign/deps/WFA2-lib/img/wfa.endsfree.png b/src/common/wflign/deps/WFA2-lib/img/wfa.endsfree.png deleted file mode 100644 index 5eac1ee1553355bacdb23e92959816b54eadbcf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68149 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 diff --git a/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c b/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c index 96831937..e0712d6b 100644 --- a/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c +++ b/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c @@ -612,6 +612,3 @@ void mm_allocator_print( mm_allocator_print_allocator_requests(stream,mm_allocator,false); } } - - - diff --git a/src/common/wflign/deps/WFA2-lib/system/mm_stack.c b/src/common/wflign/deps/WFA2-lib/system/mm_stack.c index abb86d21..5a0ae46a 100644 --- a/src/common/wflign/deps/WFA2-lib/system/mm_stack.c +++ b/src/common/wflign/deps/WFA2-lib/system/mm_stack.c @@ -266,5 +266,3 @@ void mm_stack_print( fprintf(stream," => Segments.size %" PRIu64 " MB\n",segment_size/(1024*1024)); fprintf(stream," => Memory.available %" PRIu64 " MB\n",num_segments*(segment_size/(1024*1024))); } - - diff --git a/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h b/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h index 55b1b98a..b2b7c376 100644 --- a/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h +++ b/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h @@ -33,9 +33,6 @@ #ifndef PROFILER_COUNTER_H_ #define PROFILER_COUNTER_H_ -#include -#include - /* * Counters */ diff --git a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h index d3aee5e9..5d530382 100644 --- a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h +++ b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h @@ -33,7 +33,6 @@ #ifndef PROFILER_TIMER_H #define PROFILER_TIMER_H -#include #include "profiler_counter.h" /* diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh index 0aa9c5ef..707b0dc5 100755 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh @@ -8,14 +8,6 @@ # Parameters FOLDER1=$1 FOLDER2=$2 -CMP_PERF=0 -if [[ "$3" == "--cmp-performance" ]] -then - CMP_PERF=1 -fi - -# Innit status OK -STATUS=0 echo "> Comparing $FOLDER1 vs $FOLDER2" for FILE_ALG1 in $FOLDER1/*.alg @@ -29,7 +21,6 @@ do # Check existence if [[ ! -f "$FILE_ALG2" ]] then - STATUS=1 echo "$FILE_ALG2 doesn't exist." continue fi @@ -38,27 +29,11 @@ do then if [[ $(diff <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG1) <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG2)) ]] then - STATUS=1 echo "Error" - continue else - STATUS=1 - echo -n "ok" # Only score + echo "ok" # Only score fi else - echo -n "OK" - fi - # Stats - if [[ $CMP_PERF == 1 ]] - then - T1=$(grep -m1 "Time.Alignment" $FOLDER1/$PREFIX.log | awk '{print $3" "$4}') - T2=$(grep -m1 "Time.Alignment" $FOLDER2/$PREFIX.log | awk '{print $3" "$4}') - M1=$(grep -m1 "Maximum resident set size" $FOLDER1/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') - M2=$(grep -m1 "Maximum resident set size" $FOLDER2/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') - echo -e "\tTIME($T1,$T2)\tMEM($M1,$M2)" - else - echo + echo "OK" fi done - -exit $STATUS diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh new file mode 100755 index 00000000..60b9f08e --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# PROJECT: Wavefront Alignments Algorithms (Unitary Tests) +# LICENCE: MIT License +# AUTHOR(S): Santiago Marco-Sola +# DESCRIPTION: Compares alignments (*.alg) from two folders +# USAGE: ./wfa.utest.performance.cmp.sh wfa_results_folder_1 wfa_results_folder_2 + +# Parameters +FOLDER1=$1 +FOLDER2=$2 + +echo "> Comparing $FOLDER1 vs $FOLDER2" +for FILE_ALG1 in $FOLDER1/*.alg +do + FILENAME=$(basename -- "$FILE_ALG1") + PREFIX=${FILENAME%.*} + FILE_ALG2="$FOLDER2/$FILENAME" + echo -ne "[UTest::$PREFIX]" + if [[ ${#PREFIX} < 15 ]]; then echo -ne " "; fi + echo -ne "\t" + # Check existence + if [[ ! -f "$FILE_ALG2" ]] + then + echo "$FILE_ALG2 doesn't exist." + continue + fi + # Check diff + if [[ $(diff $FILE_ALG1 $FILE_ALG2) ]] + then + if [[ $(diff <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG1) <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG2)) ]] + then + echo "Error" + continue + else + echo -n "OK" # Only score + fi + else + echo -n "OK" + fi + # Stats + T1=$(grep -m1 "Time.Alignment" $FOLDER1/$PREFIX.log | awk '{print $3" "$4}') + T2=$(grep -m1 "Time.Alignment" $FOLDER2/$PREFIX.log | awk '{print $3" "$4}') + M1=$(grep -m1 "Maximum resident set size" $FOLDER1/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') + M2=$(grep -m1 "Maximum resident set size" $FOLDER2/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') + echo -e "\tTIME($T1,$T2)\tMEM($M1,$M2)" +done diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh index eba3b0d7..2ee4fbaa 100755 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh @@ -38,4 +38,4 @@ rm $OUTPUT/*.log $OUTPUT/*.alg \time -v ./bin/align_benchmark -a $ALGORITHM -i ../data/sim.l100K.n1.e10.seq -o $OUTPUT/sim.l100K.e10.Wb.alg $BIWFA &> $OUTPUT/sim.l100K.e10.Wb.log # Run the check -./tests/wfa.utest.cmp.sh tests/ tests/wfa.utest.performance.check/ --cmp-performance \ No newline at end of file +./tests/wfa.utest.performance.cmp.sh tests/ tests/wfa.utest.performance.check/ \ No newline at end of file diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh index 016795fe..652ca4dd 100755 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x # PROJECT: Wavefront Alignments Algorithms (Unitary Tests) # LICENCE: MIT License # AUTHOR(S): Santiago Marco-Sola @@ -12,7 +12,7 @@ OUTPUT="./tests" LOG="./tests/wfa.utest.log" # Clear -rm $OUTPUT/*.alg $OUTPUT/*.log* &> /dev/null +rm $OUTPUT/*.alg $OUTPUT/*.log* # Run tests for opt in "--check=correct","test" \ @@ -72,30 +72,16 @@ diff tests/wfa.utest.check/test.affine.wfapt1.alg tests/wfa.utest.check/test.pb. ./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.wfapt0.alg tests/wfa.utest.check/test.biwfa.affine.wfapt0.alg >> $LOG.correct 2>&1 ./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.wfapt1.alg tests/wfa.utest.check/test.biwfa.affine.wfapt1.alg >> $LOG.correct 2>&1 -# Summary tests (*.correct,*.time,*.mem) +# Summary tests grep "Alignments.Correct" $LOG >> $LOG.correct grep "Time.Alignment" $LOG | awk '{if ($4 != "ms") print $3" "$4}' | sort -n > $LOG.time grep "Maximum resident set size" $LOG | awk '{print $6}' | sort -n > $LOG.mem -# Display performance -echo ">>> Performance Time (s): " -paste <(tail -n 4 $OUTPUT/wfa.utest.log.time) <(tail -n 4 $OUTPUT/wfa.utest.check/wfa.utest.log.time) -echo ">>> Performance Mem (KB): " -paste <(tail -n 4 $OUTPUT/wfa.utest.log.mem) <(tail -n 4 $OUTPUT/wfa.utest.check/wfa.utest.log.mem) - -# Display correct +echo -n ">>> Correct: " +tail -n 4 $OUTPUT/wfa.utest.log.time $OUTPUT/wfa.utest.check/wfa.utest.log.time +tail -n 4 $OUTPUT/wfa.utest.log.mem $OUTPUT/wfa.utest.check/wfa.utest.log.mem ./tests/wfa.utest.cmp.sh $OUTPUT $OUTPUT/wfa.utest.check -STATUS=$? -STATUS_EXIT=$(grep "Exit status:" $LOG | grep -v "Exit status: 0" | sort | uniq -c | tr '\n' ' ') -STATUS_SIGNAL=$(grep "Command terminated by signal" $LOG | sort | uniq -c | tr '\n' ' ') -STATUS_CORRECT=$(cat $OUTPUT/wfa.utest.log.correct | awk '{print $5$6}' | sort | uniq -c | tr '\n' ' ') -echo ">>> Correct: ExitStatus($STATUS_EXIT) Signal($STATUS_SIGNAL) Correct($STATUS_CORRECT)" -if [[ $STATUS -eq 0 && "$STATUS_EXIT"=="" && "$STATUS_SIGNAL"=="" ]] -then - echo -e ">>>\n>>> ALL GOOD!\n>>>" -else - echo -e ">>>\n>>> ERROR\n>>>" -fi - -exit $STATUS +grep "Exit status:" $LOG | sort | uniq -c +grep "Command terminated by signal" $LOG | sort | uniq -c +cat $OUTPUT/wfa.utest.log.correct | awk '{print $5$6}' | sort | uniq -c diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c index de4894de..60334b43 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c @@ -51,24 +51,6 @@ #include "benchmark/benchmark_gap_affine.h" #include "benchmark/benchmark_gap_affine2p.h" -/* - * WFA lambda (custom match function) - */ -typedef struct { - char* pattern; - int pattern_length; - char* text; - int text_length; -} match_function_params_t; -match_function_params_t lambda_params; -// Simplest Extend-matching function (for testing purposes) -int lambda_function(int v,int h,void* arguments) { - // Extract parameters - match_function_params_t* const match_arguments = (match_function_params_t*)arguments; - // Check match - if (v >= match_arguments->pattern_length || h >= match_arguments->text_length) return 0; - return (match_arguments->pattern[v] == match_arguments->text[h]); -} /* * Algorithms */ @@ -221,6 +203,10 @@ wavefront_aligner_t* align_input_configure_wavefront( // Select alignment form attributes.alignment_form.span = (parameters.endsfree) ? alignment_endsfree : alignment_end2end; // Misc + if (parameters.wfa_match_funct_arguments != NULL) { + attributes.match_funct = parameters.wfa_match_funct; + attributes.match_funct_arguments = parameters.wfa_match_funct_arguments; + } attributes.plot.enabled = (parameters.plot != 0); attributes.plot.align_level = (parameters.plot < 0) ? -1 : parameters.plot - 1; attributes.system.verbose = parameters.verbose; @@ -247,10 +233,6 @@ void align_input_configure_global( align_input->mm_allocator = mm_allocator_new(BUFFER_SIZE_1M); // WFA if (align_benchmark_is_wavefront(parameters.algorithm)) { - if (parameters.wfa_lambda) { - align_input->wfa_match_funct = lambda_function; - align_input->wfa_match_funct_arguments = &lambda_params; - } align_input->wf_aligner = align_input_configure_wavefront(align_input); } else { align_input->wf_aligner = NULL; @@ -287,11 +269,11 @@ void align_input_configure_local( } } // Custom extend-match function - if (parameters.wfa_lambda) { - lambda_params.pattern = align_input->pattern; - lambda_params.pattern_length = align_input->pattern_length; - lambda_params.text = align_input->text; - lambda_params.text_length = align_input->text_length; + if (parameters.wfa_match_funct != NULL) { + match_function_params.pattern = align_input->pattern; + match_function_params.pattern_length = align_input->pattern_length; + match_function_params.text = align_input->text; + match_function_params.text_length = align_input->text_length; } } void align_benchmark_free( @@ -324,9 +306,7 @@ bool align_benchmark_read_input( align_input->pattern[align_input->pattern_length] = '\0'; align_input->text = *line2 + 1; align_input->text_length = line2_length - 2; - if (align_input->text[align_input->text_length] == '\n') { - align_input->text[align_input->text_length] = '\0'; - } + align_input->text[align_input->text_length] = '\0'; return true; } /* diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c index e15a532e..f6c72790 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c @@ -30,6 +30,10 @@ #include "align_benchmark_params.h" +/* + * Match function + */ +match_function_params_t match_function_params; /* * Default parameters */ @@ -80,10 +84,11 @@ align_bench_params_t parameters = { .wfa_heuristic_p2 = -1, .wfa_heuristic_p3 = -1, .wfa_memory_mode = wavefront_memory_high, + .wfa_match_funct = NULL, + .wfa_match_funct_arguments = NULL, .wfa_max_memory = UINT64_MAX, .wfa_max_score = INT_MAX, .wfa_max_threads = 1, - .wfa_lambda = false, // Other algorithms parameters .bandwidth = -1, // Misc @@ -100,6 +105,16 @@ align_bench_params_t parameters = { .progress = 100000, .verbose = 0, }; +/* + * Simplest Extend-matching function (for testing purposes) + */ +int match_function(int v,int h,void* arguments) { + // Extract parameters + match_function_params_t* match_arguments = (match_function_params_t*)arguments; + // Check match + if (v > match_arguments->pattern_length || h > match_arguments->text_length) return 0; + return (match_arguments->pattern[v] == match_arguments->text[h]); +} /* * Menu */ @@ -197,10 +212,10 @@ void parse_arguments( { "wfa-memory-mode", required_argument, 0, 1001 }, { "wfa-heuristic", required_argument, 0, 1002 }, { "wfa-heuristic-parameters", required_argument, 0, 1003 }, + { "wfa-custom-match-funct", no_argument, 0, 1004 }, { "wfa-max-memory", required_argument, 0, 1005 }, { "wfa-max-score", required_argument, 0, 1006 }, { "wfa-max-threads", required_argument, 0, 1007 }, - { "wfa-lambda", no_argument, 0, 1008 }, /* Other alignment parameters */ { "bandwidth", required_argument, 0, 2000 }, /* Misc */ @@ -386,6 +401,10 @@ void parse_arguments( } break; } + case 1004: // --wfa-custom-match-funct + parameters.wfa_match_funct = match_function; + parameters.wfa_match_funct_arguments = &match_function_params; + break; case 1005: // --wfa-max-memory parameters.wfa_max_memory = atol(optarg); break; @@ -395,9 +414,6 @@ void parse_arguments( case 1007: // --wfa-max-threads parameters.wfa_max_threads = atoi(optarg); break; - case 1008: // --wfa-lambda - parameters.wfa_lambda = true; - break; /* * Other alignment parameters */ diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h index 0602688b..889f16e0 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h @@ -60,6 +60,17 @@ typedef enum { alignment_gap_affine2p_wavefront, } alignment_algorithm_type; +/* + * Match function + */ +typedef struct { + char* pattern; + int pattern_length; + char* text; + int text_length; +} match_function_params_t; +extern match_function_params_t match_function_params; + /* * Align-benchmark Parameters */ @@ -94,10 +105,11 @@ typedef struct { int wfa_heuristic_p2; int wfa_heuristic_p3; wavefront_memory_t wfa_memory_mode; + alignment_match_funct_t wfa_match_funct; + void* wfa_match_funct_arguments; uint64_t wfa_max_memory; int wfa_max_score; int wfa_max_threads; - bool wfa_lambda; // Other algorithms parameters int bandwidth; // Misc diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c index 6a56055d..2e368e1f 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c @@ -137,15 +137,9 @@ void benchmark_edit_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - if (align_input->wfa_match_funct == NULL) { - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); - } else { - wavefront_align_lambda(wf_aligner, - align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, - align_input->pattern_length,align_input->text_length); - } + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c index faf53812..5492d1d0 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c @@ -135,15 +135,9 @@ void benchmark_gap_affine_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - if (align_input->wfa_match_funct == NULL) { - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); - } else { - wavefront_align_lambda(wf_aligner, - align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, - align_input->pattern_length,align_input->text_length); - } + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c index ba6daba4..a8305d37 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c @@ -74,15 +74,9 @@ void benchmark_gap_affine2p_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - if (align_input->wfa_match_funct == NULL) { - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); - } else { - wavefront_align_lambda(wf_aligner, - align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, - align_input->pattern_length,align_input->text_length); - } + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c index 41f679f9..45cd2392 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c @@ -73,15 +73,9 @@ void benchmark_gap_linear_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - if (align_input->wfa_match_funct == NULL) { - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); - } else { - wavefront_align_lambda(wf_aligner, - align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, - align_input->pattern_length,align_input->text_length); - } + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c index 44522db6..04d73fde 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c @@ -42,15 +42,9 @@ void benchmark_indel_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - if (align_input->wfa_match_funct == NULL) { - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); - } else { - wavefront_align_lambda(wf_aligner, - align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, - align_input->pattern_length,align_input->text_length); - } + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c index 6c1ec4b4..ccbd915e 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c @@ -47,8 +47,6 @@ void benchmark_align_input_clear( align_input->text_begin_free = 0; align_input->pattern_end_free = 0; align_input->text_end_free = 0; - align_input->wfa_match_funct = NULL; - align_input->wfa_match_funct_arguments = NULL; // Output align_input->output_file = NULL; align_input->output_full = false; diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h index 2d04c4b3..b501d057 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h @@ -62,8 +62,6 @@ typedef struct { int pattern_length; char* text; int text_length; - alignment_match_funct_t wfa_match_funct; - void* wfa_match_funct_arguments; // Penalties linear_penalties_t linear_penalties; affine_penalties_t affine_penalties; diff --git a/src/common/wflign/deps/WFA2-lib/utils/Makefile b/src/common/wflign/deps/WFA2-lib/utils/Makefile index 01665c2e..79d36bf0 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/Makefile +++ b/src/common/wflign/deps/WFA2-lib/utils/Makefile @@ -12,6 +12,7 @@ MODULES=bitmap \ dna_text \ heatmap \ sequence_buffer \ + string_padded \ vector SRCS=$(addsuffix .c, $(MODULES)) diff --git a/src/common/wflign/deps/WFA2-lib/utils/commons.h b/src/common/wflign/deps/WFA2-lib/utils/commons.h index a1f0132f..7d602434 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/commons.h +++ b/src/common/wflign/deps/WFA2-lib/utils/commons.h @@ -31,6 +31,7 @@ #pragma once +#include #include #include #include diff --git a/src/common/wflign/deps/WFA2-lib/utils/heatmap.h b/src/common/wflign/deps/WFA2-lib/utils/heatmap.h index fddadd16..9def0ed5 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/heatmap.h +++ b/src/common/wflign/deps/WFA2-lib/utils/heatmap.h @@ -31,8 +31,6 @@ #ifndef HEATMAP_H_ #define HEATMAP_H_ -#include - /* * Heatmap */ diff --git a/src/common/wflign/deps/WFA2-lib/utils/string_padded.c b/src/common/wflign/deps/WFA2-lib/utils/string_padded.c new file mode 100644 index 00000000..99c10062 --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/utils/string_padded.c @@ -0,0 +1,140 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: Padded string module to avoid handling corner conditions + */ + +#include "utils/commons.h" +#include "system/mm_allocator.h" +#include "utils/string_padded.h" + +/* + * Strings (text/pattern) padded + */ +void strings_padded_add_padding( + const char* const buffer, + const int buffer_length, + const int begin_padding_length, + const int end_padding_length, + const char padding_value, + char** const buffer_padded, + char** const buffer_padded_begin, + const bool reverse_sequence, + mm_allocator_t* const mm_allocator) { + // Allocate + const int buffer_padded_length = begin_padding_length + buffer_length + end_padding_length; + *buffer_padded = mm_allocator_malloc(mm_allocator,buffer_padded_length); + // Add begin padding + memset(*buffer_padded,padding_value,begin_padding_length); + // Copy buffer + *buffer_padded_begin = *buffer_padded + begin_padding_length; + if (reverse_sequence) { + int i; + for (i=0;imm_allocator = mm_allocator; + // Compute padding dimensions + const int pattern_begin_padding_length = 0; + const int pattern_end_padding_length = padding_length; + const int text_begin_padding_length = 0; + const int text_end_padding_length = padding_length; + // Add padding + strings_padded_add_padding( + pattern,pattern_length, + pattern_begin_padding_length,pattern_end_padding_length,'?', + &(strings_padded->pattern_padded_buffer), + &(strings_padded->pattern_padded), + reverse_sequences,mm_allocator); + strings_padded_add_padding( + text,text_length, + text_begin_padding_length,text_end_padding_length,'!', + &(strings_padded->text_padded_buffer), + &(strings_padded->text_padded), + reverse_sequences,mm_allocator); + // Return + return strings_padded; +} +strings_padded_t* strings_padded_new_rhomb( + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const int padding_length, + const bool reverse_sequences, + mm_allocator_t* const mm_allocator) { + // Allocate + strings_padded_t* const strings_padded = + mm_allocator_alloc(mm_allocator,strings_padded_t); + strings_padded->mm_allocator = mm_allocator; + // Compute padding dimensions + const int pattern_begin_padding_length = text_length + padding_length; + const int pattern_end_padding_length = pattern_length + text_length + padding_length; + const int text_begin_padding_length = padding_length; + const int text_end_padding_length = text_length + padding_length; + // Add padding + strings_padded_add_padding( + pattern,pattern_length, + pattern_begin_padding_length,pattern_end_padding_length,'?', + &(strings_padded->pattern_padded_buffer), + &(strings_padded->pattern_padded), + reverse_sequences,mm_allocator); + strings_padded_add_padding( + text,text_length, + text_begin_padding_length,text_end_padding_length,'!', + &(strings_padded->text_padded_buffer), + &(strings_padded->text_padded), + reverse_sequences,mm_allocator); + // Set lengths + strings_padded->pattern_length = pattern_length; + strings_padded->text_length = text_length; + // Return + return strings_padded; +} +void strings_padded_delete(strings_padded_t* const strings_padded) { + mm_allocator_free(strings_padded->mm_allocator,strings_padded->pattern_padded_buffer); + mm_allocator_free(strings_padded->mm_allocator,strings_padded->text_padded_buffer); + mm_allocator_free(strings_padded->mm_allocator,strings_padded); +} diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h b/src/common/wflign/deps/WFA2-lib/utils/string_padded.h similarity index 57% rename from src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h rename to src/common/wflign/deps/WFA2-lib/utils/string_padded.h index 05085ba8..975594d8 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h +++ b/src/common/wflign/deps/WFA2-lib/utils/string_padded.h @@ -26,32 +26,48 @@ * * PROJECT: Wavefront Alignment Algorithms * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module to check for the termination of an alignment + * DESCRIPTION: Padded string module to avoid handling corner conditions */ -#ifndef WAVEFRONT_TERMINATION_H_ -#define WAVEFRONT_TERMINATION_H_ - -#include "wavefront_aligner.h" +#ifndef STRING_PADDED_H_ +#define STRING_PADDED_H_ /* - * Necessary condition for ends-free termination + * Strings Padded */ -#define WF_TERMINATION_ENDSFREE(h,v) ((h >= text_length) || (v >= pattern_length)) +typedef struct { + // Dimensions + int pattern_length; + int text_length; + // Padded strings + char* pattern_padded; + char* text_padded; + // MM + char* pattern_padded_buffer; + char* text_padded_buffer; + mm_allocator_t* mm_allocator; +} strings_padded_t; /* - * Detect alignment termination (end of alignment) + * Strings (text/pattern) padded */ -bool wavefront_termination_end2end( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int score_mod); -bool wavefront_termination_endsfree( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int k, - const wf_offset_t offset); +strings_padded_t* strings_padded_new( + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const int padding_length, + const bool reverse_sequences, + mm_allocator_t* const mm_allocator); +strings_padded_t* strings_padded_new_rhomb( + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const int padding_length, + const bool reverse_sequences, + mm_allocator_t* const mm_allocator); +void strings_padded_delete( + strings_padded_t* const strings_padded); -#endif /* WAVEFRONT_TERMINATION_H_ */ +#endif /* STRING_PADDED_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/utils/vector.h b/src/common/wflign/deps/WFA2-lib/utils/vector.h index 2c5dcf06..4bd4776b 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/vector.h +++ b/src/common/wflign/deps/WFA2-lib/utils/vector.h @@ -33,6 +33,8 @@ #ifndef VECTOR_H_ #define VECTOR_H_ +#include + /* * Checkers */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/Makefile b/src/common/wflign/deps/WFA2-lib/wavefront/Makefile index 1b372eeb..c30efdde 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/Makefile +++ b/src/common/wflign/deps/WFA2-lib/wavefront/Makefile @@ -24,15 +24,11 @@ MODULES=wavefront_align \ wavefront_debug \ wavefront_display \ wavefront_extend \ - wavefront_extend_kernels_avx \ - wavefront_extend_kernels \ wavefront_heuristic \ wavefront_pcigar \ wavefront_penalties \ - wavefront_sequences \ wavefront_plot \ wavefront_slab \ - wavefront_termination \ wavefront_unialign \ wavefront diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c index f35d023c..8705d3af 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c @@ -108,89 +108,49 @@ void wavefront_align_unidirectional_cleanup( } } void wavefront_align_unidirectional( - wavefront_aligner_t* const wf_aligner) { + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length) { + // Prepare alignment + wavefront_unialign_init( + wf_aligner,pattern,pattern_length,text,text_length, + affine2p_matrix_M,affine2p_matrix_M); + // DEBUG + wavefront_debug_prologue(wf_aligner,pattern,pattern_length,text,text_length); // Wavefront align sequences - wavefront_unialign_init(wf_aligner,affine2p_matrix_M,affine2p_matrix_M); // Init - wavefront_unialign(wf_aligner); // Align + wavefront_unialign(wf_aligner); // Finish if (wf_aligner->align_status.status == WF_STATUS_MAX_SCORE_REACHED) return; // Alignment paused wavefront_align_unidirectional_cleanup(wf_aligner); + // DEBUG + wavefront_debug_epilogue(wf_aligner); + wavefront_debug_check_correct(wf_aligner); } /* * Wavefront Alignment Bidirectional */ void wavefront_align_bidirectional( - wavefront_aligner_t* const wf_aligner) { - // Bidirectional alignment - wavefront_bialign(wf_aligner); // Align - // Finish - wf_aligner->align_status.memory_used = wavefront_aligner_get_size(wf_aligner); -} -/* - * Wavefront Alignment Dispatcher - */ -int wavefront_align_lambda( wavefront_aligner_t* const wf_aligner, - alignment_match_funct_t match_funct, - void* match_funct_arguments, + const char* const pattern, const int pattern_length, + const char* const text, const int text_length) { - // Checks - wavefront_align_checks(wf_aligner,pattern_length,text_length); - wavefront_debug_begin(wf_aligner); - // Plot - if (wf_aligner->plot != NULL) wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); - // Dispatcher - if (wf_aligner->bialigner == NULL) { - // Prepare Sequences - wavefront_sequences_init_lambda(&wf_aligner->sequences, - match_funct,match_funct_arguments, - pattern_length,text_length,false); - wavefront_align_unidirectional(wf_aligner); - } else { - // Prepare Sequences - wavefront_bialigner_set_sequences_lambda(wf_aligner->bialigner, - match_funct,match_funct_arguments, - pattern_length,text_length); - // Align - wavefront_align_bidirectional(wf_aligner); - } // DEBUG - wavefront_debug_end(wf_aligner); - wavefront_debug_check_correct(wf_aligner); - // Return - return wf_aligner->align_status.status; -} -int wavefront_align_packed2bits( - wavefront_aligner_t* const wf_aligner, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length) { - // Checks - wavefront_align_checks(wf_aligner,pattern_length,text_length); - wavefront_debug_begin(wf_aligner); - // Plot - if (wf_aligner->plot != NULL) wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); - // Dispatcher - if (wf_aligner->bialigner == NULL) { - // Prepare Sequences - wavefront_sequences_init_packed2bits(&wf_aligner->sequences, - pattern,pattern_length,text,text_length,false); - wavefront_align_unidirectional(wf_aligner); - } else { - // Prepare Sequences - wavefront_bialigner_set_sequences_packed2bits(wf_aligner->bialigner, - pattern,pattern_length,text,text_length); - // Align - wavefront_align_bidirectional(wf_aligner); - } + wavefront_debug_prologue(wf_aligner,pattern,pattern_length,text,text_length); + // Bidirectional alignment + wavefront_bialign(wf_aligner,pattern,pattern_length,text,text_length); + // Finish + const uint64_t memory_used = wavefront_aligner_get_size(wf_aligner); + wf_aligner->align_status.memory_used = memory_used; // DEBUG - wavefront_debug_end(wf_aligner); + wavefront_debug_epilogue(wf_aligner); wavefront_debug_check_correct(wf_aligner); - // Return - return wf_aligner->align_status.status; } +/* + * Wavefront Alignment Dispatcher + */ int wavefront_align( wavefront_aligner_t* const wf_aligner, const char* const pattern, @@ -199,31 +159,19 @@ int wavefront_align( const int text_length) { // Checks wavefront_align_checks(wf_aligner,pattern_length,text_length); - wavefront_debug_begin(wf_aligner); // Plot - if (wf_aligner->plot != NULL) wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); + if (wf_aligner->plot != NULL) { + wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); + } // Dispatcher - if (wf_aligner->bialigner == NULL) { - // Prepare Sequences - wavefront_sequences_init_ascii(&wf_aligner->sequences, - pattern,pattern_length,text,text_length,false); - wavefront_align_unidirectional(wf_aligner); + if (wf_aligner->bialigner != NULL) { + wavefront_align_bidirectional(wf_aligner,pattern,pattern_length,text,text_length); } else { - // Prepare Sequences - wavefront_bialigner_set_sequences_ascii(wf_aligner->bialigner, - pattern,pattern_length,text,text_length); - // Align - wavefront_align_bidirectional(wf_aligner); + wavefront_align_unidirectional(wf_aligner,pattern,pattern_length,text,text_length); } - // DEBUG - wavefront_debug_end(wf_aligner); - wavefront_debug_check_correct(wf_aligner); // Return return wf_aligner->align_status.status; } -/* - * Wavefront Alignment Resume (Experimental) - */ int wavefront_align_resume( wavefront_aligner_t* const wf_aligner) { // Parameters @@ -242,6 +190,7 @@ int wavefront_align_resume( } wavefront_align_unidirectional_cleanup(wf_aligner); // DEBUG + wavefront_debug_epilogue(wf_aligner); wavefront_debug_check_correct(wf_aligner); // Return return align_status->status; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h index 85180add..71f97230 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h @@ -42,15 +42,5 @@ int wavefront_align( const int pattern_length, const char* const text, const int text_length); -int wavefront_align_lambda( - wavefront_aligner_t* const wf_aligner, - alignment_match_funct_t const match_funct, - void* match_funct_arguments, - const int pattern_length, - const int text_length); -int wavefront_align_packed2bits( - wavefront_aligner_t* const wf_aligner, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length); +int wavefront_align_resume( + wavefront_aligner_t* const wf_aligner); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c index a2273578..dadb777a 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c @@ -34,8 +34,6 @@ #include "wavefront_components.h" #include "wavefront_heuristic.h" #include "wavefront_plot.h" -#include "wavefront_compute.h" -#include "wavefront_sequences.h" /* * Configuration @@ -53,13 +51,6 @@ char* wf_error_msg[] = /* WF_STATUS_UNFEASIBLE == -1 */ "[WFA] Alignment unfeasible (possible due to heuristic parameters)", /* WF_STATUS_SUCCESSFUL == 0 */ "[WFA] Alignment finished successfully", }; -char* wf_error_msg_short[] = -{ - /* WF_STATUS_OOM == -3 */ "OOM", - /* WF_STATUS_MAX_SCORE_REACHED == -2 */ "MaxScore", - /* WF_STATUS_UNFEASIBLE == -1 */ "Unfeasible", - /* WF_STATUS_SUCCESSFUL == 0 */ "OK", -}; char* wavefront_align_strerror(const int error_code) { if (error_code > 0) { fprintf(stderr,"[WFA] Internal alignment error code (%d)",error_code); @@ -67,9 +58,6 @@ char* wavefront_align_strerror(const int error_code) { } return wf_error_msg[error_code+3]; } -char* wavefront_align_strerror_short(const int error_code) { - return wf_error_msg_short[error_code+3]; -} /* * Setup */ @@ -185,6 +173,9 @@ void wavefront_aligner_init_alignment( // Memory mode wf_aligner->memory_mode = attributes->memory_mode; wavefront_aligner_init_heuristic(wf_aligner,attributes); + // Custom matching functions + wf_aligner->match_funct = attributes->match_funct; + wf_aligner->match_funct_arguments = attributes->match_funct_arguments; } wavefront_aligner_t* wavefront_aligner_new( wavefront_aligner_attr_t* attributes) { @@ -220,7 +211,7 @@ wavefront_aligner_t* wavefront_aligner_new( wf_aligner->mm_allocator); } // Sequences - wavefront_sequences_allocate(&wf_aligner->sequences); + wf_aligner->sequences = NULL; // CIGAR const int cigar_length = (score_only) ? 10 : 2*(PATTERN_LENGTH_INIT+TEXT_LENGTH_INIT); wf_aligner->cigar = cigar_new(cigar_length,wf_aligner->mm_allocator); @@ -231,6 +222,11 @@ wavefront_aligner_t* wavefront_aligner_new( } void wavefront_aligner_reap( wavefront_aligner_t* const wf_aligner) { + // Padded sequences + if (wf_aligner->sequences != NULL) { + strings_padded_delete(wf_aligner->sequences); + wf_aligner->sequences = NULL; + } // Select alignment mode if (wf_aligner->bialigner != NULL) { wavefront_bialigner_reap(wf_aligner->bialigner); @@ -246,8 +242,10 @@ void wavefront_aligner_delete( // Parameters mm_allocator_t* const mm_allocator = wf_aligner->mm_allocator; const bool mm_allocator_own = wf_aligner->mm_allocator_own; - // Sequences - wavefront_sequences_free(&wf_aligner->sequences); + // Padded sequences + if (wf_aligner->sequences != NULL) { + strings_padded_delete(wf_aligner->sequences); + } // Select alignment mode if (wf_aligner->bialigner != NULL) { wavefront_bialigner_delete(wf_aligner->bialigner); @@ -266,143 +264,7 @@ void wavefront_aligner_delete( // MM mm_allocator_free(mm_allocator,wf_aligner); if (mm_allocator_own) { - mm_allocator_delete(mm_allocator); - } -} -/* - * Initialize wf-alignment conditions - */ -void wavefront_aligner_init_wf_m( - wavefront_aligner_t* const wf_aligner) { - // Parameters - wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; - wavefront_components_t* const wf_components = &wf_aligner->wf_components; - const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; - wavefront_penalties_t* const penalties = &wf_aligner->penalties; - alignment_form_t* const form = &wf_aligner->alignment_form; - // Consider ends-free - const int hi = (penalties->match==0) ? form->text_begin_free : 0; - const int lo = (penalties->match==0) ? -form->pattern_begin_free : 0; - // Compute dimensions - int effective_lo, effective_hi; - wavefront_compute_limits_output(wf_aligner,lo,hi,&effective_lo,&effective_hi); - // Initialize end2end (wavefront zero) - wf_components->mwavefronts[0] = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); - wf_components->mwavefronts[0]->offsets[0] = 0; - wf_components->mwavefronts[0]->lo = lo; - wf_components->mwavefronts[0]->hi = hi; - // Store initial BT-piggypack element - if (wf_components->bt_piggyback) { - const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,0); - wf_components->mwavefronts[0]->bt_pcigar[0] = 0; - wf_components->mwavefronts[0]->bt_prev[0] = block_idx; - } - // Initialize ends-free - if (form->span == alignment_endsfree && penalties->match == 0) { - // Text begin-free - const int text_begin_free = form->text_begin_free; - int h; - for (h=1;h<=text_begin_free;++h) { - const int k = DPMATRIX_DIAGONAL(h,0); - wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(h,0); - if (wf_components->bt_piggyback) { - const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,h); - wf_components->mwavefronts[0]->bt_pcigar[k] = 0; - wf_components->mwavefronts[0]->bt_prev[k] = block_idx; - } - } - // Pattern begin-free - const int pattern_begin_free = form->pattern_begin_free; - int v; - for (v=1;v<=pattern_begin_free;++v) { - const int k = DPMATRIX_DIAGONAL(0,v); - wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(0,v); - if (wf_components->bt_piggyback) { - const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,v,0); - wf_components->mwavefronts[0]->bt_pcigar[k] = 0; - wf_components->mwavefronts[0]->bt_prev[k] = block_idx; - } - } - } - // Nullify unused WFs - if (distance_metric <= gap_linear) return; - wf_components->d1wavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - if (distance_metric==gap_affine) return; - wf_components->d2wavefronts[0] = NULL; - wf_components->i2wavefronts[0] = NULL; -} -void wavefront_aligner_init_wf( - wavefront_aligner_t* const wf_aligner) { - // Parameters - wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; - wavefront_components_t* const wf_components = &wf_aligner->wf_components; - const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; - // Init wavefronts - if (wf_aligner->component_begin == affine2p_matrix_M) { - // Initialize - wavefront_aligner_init_wf_m(wf_aligner); - // Nullify unused WFs - if (distance_metric <= gap_linear) return; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = NULL; - if (distance_metric == gap_affine) return; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = NULL; - } else { - // Compute dimensions - int effective_lo, effective_hi; // Effective lo/hi - wavefront_compute_limits_output(wf_aligner,0,0,&effective_lo,&effective_hi); - wavefront_t* const wavefront = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); - // Initialize - switch (wf_aligner->component_begin) { - case affine2p_matrix_I1: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = wavefront; - wf_components->i1wavefronts[0]->offsets[0] = 0; - wf_components->i1wavefronts[0]->lo = 0; - wf_components->i1wavefronts[0]->hi = 0; - wf_components->d1wavefronts[0] = NULL; - // Nullify unused WFs - if (distance_metric==gap_affine) return; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = NULL; - break; - case affine2p_matrix_I2: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = NULL; - wf_components->i2wavefronts[0] = wavefront; - wf_components->i2wavefronts[0]->offsets[0] = 0; - wf_components->i2wavefronts[0]->lo = 0; - wf_components->i2wavefronts[0]->hi = 0; - wf_components->d2wavefronts[0] = NULL; - break; - case affine2p_matrix_D1: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = wavefront; - wf_components->d1wavefronts[0]->offsets[0] = 0; - wf_components->d1wavefronts[0]->lo = 0; - wf_components->d1wavefronts[0]->hi = 0; - // Nullify unused WFs - if (distance_metric==gap_affine) return; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = NULL; - break; - case affine2p_matrix_D2: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = NULL; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = wavefront; - wf_components->d2wavefronts[0]->offsets[0] = 0; - wf_components->d2wavefronts[0]->lo = 0; - wf_components->d2wavefronts[0]->hi = 0; - break; - default: - break; - } + mm_allocator_delete(wf_aligner->mm_allocator); } } /* @@ -496,6 +358,20 @@ void wavefront_aligner_set_heuristic_zdrop( wavefront_bialigner_set_heuristic(wf_aligner->bialigner,&wf_aligner->heuristic); } } +/* + * Match-funct configuration + */ +void wavefront_aligner_set_match_funct( + wavefront_aligner_t* const wf_aligner, + int (*match_funct)(int,int,void*), + void* const match_funct_arguments) { + wf_aligner->match_funct = match_funct; + wf_aligner->match_funct_arguments = match_funct_arguments; + if (wf_aligner->bialigner != NULL) { + wavefront_bialigner_set_match_funct( + wf_aligner->bialigner,match_funct,match_funct_arguments); + } +} /* * System configuration */ @@ -520,22 +396,22 @@ void wavefront_aligner_set_max_memory( } } void wavefront_aligner_set_max_num_threads( - wavefront_aligner_t* const wf_aligner, - const int max_num_threads) { - wf_aligner->system.max_num_threads = max_num_threads; - if (wf_aligner->bialigner != NULL) { - wavefront_bialigner_set_max_num_threads( - wf_aligner->bialigner,max_num_threads); - } + wavefront_aligner_t* const wf_aligner, + const int max_num_threads) { + wf_aligner->system.max_num_threads = max_num_threads; + if (wf_aligner->bialigner != NULL) { + wavefront_bialigner_set_max_num_threads( + wf_aligner->bialigner,max_num_threads); + } } void wavefront_aligner_set_min_offsets_per_thread( - wavefront_aligner_t* const wf_aligner, - const int min_offsets_per_thread) { - wf_aligner->system.min_offsets_per_thread = min_offsets_per_thread; - if (wf_aligner->bialigner != NULL) { - wavefront_bialigner_set_min_offsets_per_thread( - wf_aligner->bialigner,min_offsets_per_thread); - } + wavefront_aligner_t* const wf_aligner, + const int min_offsets_per_thread) { + wf_aligner->system.min_offsets_per_thread = min_offsets_per_thread; + if (wf_aligner->bialigner != NULL) { + wavefront_bialigner_set_min_offsets_per_thread( + wf_aligner->bialigner,min_offsets_per_thread); + } } /* * Utils @@ -560,28 +436,29 @@ uint64_t wavefront_aligner_get_size( /* * Display */ -void wavefront_aligner_print_mode( +void wavefront_aligner_print_type( FILE* const stream, wavefront_aligner_t* const wf_aligner) { - if (wf_aligner->align_mode_tag != NULL) { - fprintf(stream,"%s::",wf_aligner->align_mode_tag); - } - switch (wf_aligner->align_mode) { - case wf_align_biwfa: - fprintf(stream,"BiWFA"); - break; - case wf_align_biwfa_breakpoint_forward: - fprintf(stream,"BiWFA::Forward"); - break; - case wf_align_biwfa_breakpoint_reverse: - fprintf(stream,"BiWFA::Reverse"); - break; - case wf_align_biwfa_subsidiary: - fprintf(stream,"BiWFA::SubWFA"); - break; - default: - fprintf(stream,"WFA"); - break; + if (wf_aligner->align_mode_tag == NULL) { + switch (wf_aligner->align_mode) { + case wf_align_biwfa: + fprintf(stream,"BiWFA"); + break; + case wf_align_biwfa_breakpoint_forward: + fprintf(stream,"BiWFA::Forward"); + break; + case wf_align_biwfa_breakpoint_reverse: + fprintf(stream,"BiWFA::Reverse"); + break; + case wf_align_biwfa_subsidiary: + fprintf(stream,"BiWFA::SubWFA"); + break; + default: + fprintf(stream,"WFA"); + break; + } + } else { + fprintf(stream,"%s",wf_aligner->align_mode_tag); } } void wavefront_aligner_print_scope( @@ -600,19 +477,14 @@ void wavefront_aligner_print_scope( wf_aligner->alignment_form.text_end_free); } } -void wavefront_aligner_print_conf( +void wavefront_aligner_print_mode( FILE* const stream, wavefront_aligner_t* const wf_aligner) { - fprintf(stream,"("); + fprintf(stream,"(%s,",(wf_aligner->alignment_scope==compute_score)?"Score":"Alg"); switch (wf_aligner->memory_mode) { - case wavefront_memory_high: fprintf(stream,"MHigh"); break; - case wavefront_memory_med: fprintf(stream,"MMed"); break; - case wavefront_memory_low: fprintf(stream,"MLow"); break; - case wavefront_memory_ultralow: fprintf(stream,"BiWFA"); break; - } - if (wf_aligner->system.max_alignment_score == INT_MAX) { - fprintf(stream,",inf)"); - } else { - fprintf(stream,",%d)",wf_aligner->system.max_alignment_score); + case wavefront_memory_high: fprintf(stream,"MHigh)"); break; + case wavefront_memory_med: fprintf(stream,"MMed)"); break; + case wavefront_memory_low: fprintf(stream,"MLow)"); break; + case wavefront_memory_ultralow: fprintf(stream,"BiWFA)"); break; } } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c index 5869d214..d6427a2f 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c @@ -46,6 +46,9 @@ wavefront_aligner_attr_t wavefront_aligner_attr_default = { .text_begin_free = 0, .text_end_free = 0, }, + // Custom matching functions + .match_funct = NULL, // Use default match-compare function + .match_funct_arguments = NULL, // No arguments // Penalties .linear_penalties = { .match = 0, diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h index 413144d0..bac851af 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h @@ -32,7 +32,6 @@ #ifndef WAVEFRONT_ATTRIBUTES_H_ #define WAVEFRONT_ATTRIBUTES_H_ -#include "utils/commons.h" #include "alignment/cigar.h" #include "alignment/affine_penalties.h" #include "alignment/affine2p_penalties.h" @@ -66,6 +65,26 @@ typedef struct { int text_end_free; // Allow free-gap at the end of the text } alignment_form_t; +/* + * Custom extend-match function, e.g.: + * + * typedef struct { + * char* pattern; + * int pattern_length; + * char* text; + * int text_length; + * } match_function_params_t; + * + * int match_function(int v,int h,void* arguments) { + * // Extract parameters + * match_function_params_t* match_arguments = (match_function_params_t*)arguments; + * // Check match + * if (v > match_arguments->pattern_length || h > match_arguments->text_length) return 0; + * return (match_arguments->pattern[v] == match_arguments->text[h]); + * } + */ +typedef int (*alignment_match_funct_t)(int,int,void*); + /* * Alignment system configuration */ @@ -122,6 +141,9 @@ typedef struct { wavefront_heuristic_t heuristic; // Wavefront heuristic // Memory model wavefront_memory_t memory_mode; // Wavefront memory strategy (modular wavefronts and piggyback) + // Custom function to compare sequences + alignment_match_funct_t match_funct; // Custom matching function (match(v,h,args)) + void* match_funct_arguments; // Generic arguments passed to matching function (args) // External MM (instead of allocating one inside) mm_allocator_t* mm_allocator; // MM-Allocator // Display diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c index 962cfa33..fbb39060 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c @@ -226,9 +226,8 @@ void wavefront_backtrace_linear( const int alignment_k, const wf_offset_t alignment_offset) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; const wavefront_penalties_t* const penalties = &wf_aligner->penalties; const distance_metric_t distance_metric = penalties->distance_metric; // Prepare cigar @@ -324,9 +323,8 @@ void wavefront_backtrace_affine( const int alignment_k, const wf_offset_t alignment_offset) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; const wavefront_penalties_t* const penalties = &wf_aligner->penalties; const distance_metric_t distance_metric = penalties->distance_metric; // Prepare cigar @@ -516,8 +514,8 @@ void wavefront_backtrace_affine( // DEBUG if (v != 0 || h != 0 || (score != 0 && penalties->match == 0)) { fprintf(stderr,"[WFA::Backtrace] I?/D?-Beginning backtrace error\n"); - fprintf(stderr,">%.*s\n",pattern_length,sequences->pattern); - fprintf(stderr,"<%.*s\n",text_length,sequences->text); + fprintf(stderr,">%.*s\n",pattern_length,wf_aligner->pattern); + fprintf(stderr,"<%.*s\n",text_length,wf_aligner->text); exit(-1); } } @@ -552,12 +550,18 @@ void wavefront_backtrace_pcigar( const int end_v = WAVEFRONT_V(alignment_k,alignment_offset); const int end_h = WAVEFRONT_H(alignment_k,alignment_offset); if (wf_aligner->penalties.distance_metric <= gap_linear) { - wf_backtrace_buffer_unpack_cigar_linear( - bt_buffer,&wf_aligner->sequences, + wf_backtrace_buffer_unpack_cigar_linear(bt_buffer, + wf_aligner->pattern,wf_aligner->pattern_length, + wf_aligner->text,wf_aligner->text_length, + wf_aligner->match_funct, + wf_aligner->match_funct_arguments, begin_v,begin_h,end_v,end_h,wf_aligner->cigar); } else { - wf_backtrace_buffer_unpack_cigar_affine( - bt_buffer,&wf_aligner->sequences, + wf_backtrace_buffer_unpack_cigar_affine(bt_buffer, + wf_aligner->pattern,wf_aligner->pattern_length, + wf_aligner->text,wf_aligner->text_length, + wf_aligner->match_funct, + wf_aligner->match_funct_arguments, begin_v,begin_h,end_v,end_h,wf_aligner->cigar); } } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c index e8363740..ab101279 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "wavefront_backtrace_buffer.h" -#include "wavefront_sequences.h" /* * Config @@ -267,15 +266,17 @@ bt_block_t* wf_backtrace_buffer_traceback_pcigar( } void wf_backtrace_buffer_unpack_cigar_linear( wf_backtrace_buffer_t* const bt_buffer, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, const int begin_v, const int begin_h, const int end_v, const int end_h, cigar_t* const cigar) { - // Parameters - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; // Clear cigar char* cigar_buffer = cigar->operations; cigar->begin_offset = 0; @@ -292,7 +293,9 @@ void wf_backtrace_buffer_unpack_cigar_linear( // Unpack block int cigar_block_length = 0; pcigar_unpack_linear( - palignment_blocks[i],sequences,&v,&h, + palignment_blocks[i], + pattern,pattern_length,text,text_length, + match_funct,match_funct_arguments,&v,&h, cigar_buffer,&cigar_block_length); // Update CIGAR cigar_buffer += cigar_block_length; @@ -311,15 +314,17 @@ void wf_backtrace_buffer_unpack_cigar_linear( } void wf_backtrace_buffer_unpack_cigar_affine( wf_backtrace_buffer_t* const bt_buffer, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, const int begin_v, const int begin_h, const int end_v, const int end_h, cigar_t* const cigar) { - // Parameters - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; // Clear cigar char* cigar_buffer = cigar->operations; cigar->begin_offset = 0; @@ -337,7 +342,9 @@ void wf_backtrace_buffer_unpack_cigar_affine( // Unpack block int cigar_block_length = 0; pcigar_unpack_affine( - palignment_blocks[i],sequences,&v,&h, + palignment_blocks[i], + pattern,pattern_length,text,text_length, + match_funct,match_funct_arguments,&v,&h, cigar_buffer,&cigar_block_length,¤t_matrix_type); // Update CIGAR cigar_buffer += cigar_block_length; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h index 3b2f8084..392b8c8c 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h @@ -119,7 +119,12 @@ bt_block_t* wf_backtrace_buffer_traceback_pcigar( bt_block_t* bt_block); void wf_backtrace_buffer_unpack_cigar_linear( wf_backtrace_buffer_t* const bt_buffer, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, const int begin_v, const int begin_h, const int end_v, @@ -127,7 +132,12 @@ void wf_backtrace_buffer_unpack_cigar_linear( cigar_t* const cigar); void wf_backtrace_buffer_unpack_cigar_affine( wf_backtrace_buffer_t* const bt_buffer, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, const int begin_v, const int begin_h, const int end_v, diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c index fc8c0690..f802bbb7 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "wfa.h" +#include "utils/string_padded.h" #include "wavefront_backtrace_offload.h" /* diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c index c862216e..2ecd41b6 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c @@ -72,81 +72,6 @@ void wavefront_bialign_debug( } fprintf(stderr,")\n"); } -/* - * Init - */ -void wavefront_bialign_init( - wavefront_bialigner_t* const bialigner, - const distance_metric_t distance_metric, - alignment_form_t* const form, - const affine2p_matrix_type component_begin, - const affine2p_matrix_type component_end, - const int verbose) { - // Parameters - wavefront_aligner_t* const alg_forward = bialigner->alg_forward; - wavefront_aligner_t* const alg_reverse = bialigner->alg_reverse; - // Resize wavefront aligner - wavefront_unialign_resize(alg_forward); - wavefront_unialign_resize(alg_reverse); - // Configure WF-compute function (global) - switch (distance_metric) { - case indel: - case edit: - bialigner->wf_align_compute = &wavefront_compute_edit; - break; - case gap_linear: - bialigner->wf_align_compute = &wavefront_compute_linear; - break; - case gap_affine: - bialigner->wf_align_compute = &wavefront_compute_affine; - break; - case gap_affine_2p: - bialigner->wf_align_compute = &wavefront_compute_affine2p; - break; - default: - fprintf(stderr,"[WFA] Distance function not implemented\n"); - exit(1); - break; - } - // Configure form forward and reverse - alignment_span_t span_forward = - (form->pattern_begin_free > 0 || form->text_begin_free > 0) ? - alignment_endsfree : alignment_end2end; - alignment_form_t form_forward = { - .span = span_forward, - .pattern_begin_free = form->pattern_begin_free, - .pattern_end_free = 0, - .text_begin_free = form->text_begin_free, - .text_end_free = 0, - }; - alignment_span_t span_reverse = - (form->pattern_end_free > 0 || form->text_end_free > 0) ? - alignment_endsfree : alignment_end2end; - alignment_form_t form_reverse = { - .span = span_reverse, - .pattern_begin_free = form->pattern_end_free, - .pattern_end_free = 0, - .text_begin_free = form->text_end_free, - .text_end_free = 0, - }; - // Initialize wavefront (forward) - alg_forward->align_status.num_null_steps = 0; - alg_forward->alignment_form = form_forward; - alg_forward->component_begin = component_begin; - alg_forward->component_end = component_end; - wavefront_aligner_init_wf(alg_forward); - // Initialize wavefront (reverse) - alg_reverse->align_status.num_null_steps = 0; - alg_reverse->alignment_form = form_reverse; - alg_reverse->component_begin = component_end; - alg_reverse->component_end = component_begin; - wavefront_aligner_init_wf(alg_reverse); - // DEBUG - if (verbose >= 2) { - wavefront_debug_begin(alg_forward); - wavefront_debug_begin(alg_reverse); - } -} /* * Bidirectional check breakpoints */ @@ -160,9 +85,8 @@ void wavefront_bialign_breakpoint_indel2indel( const affine2p_matrix_type component, wf_bialign_breakpoint_t* const breakpoint) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int text_length = sequences->text_length; - const int pattern_length = sequences->pattern_length; + const int text_length = wf_aligner->text_length; + const int pattern_length = wf_aligner->pattern_length; const int gap_open = (component==affine2p_matrix_I1 || component==affine2p_matrix_D1) ? wf_aligner->penalties.gap_opening1 : wf_aligner->penalties.gap_opening2; @@ -217,9 +141,8 @@ void wavefront_bialign_breakpoint_m2m( wavefront_t* const mwf_1, wf_bialign_breakpoint_t* const breakpoint) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int text_length = sequences->text_length; - const int pattern_length = sequences->pattern_length; + const int text_length = wf_aligner->text_length; + const int pattern_length = wf_aligner->pattern_length; // Check wavefronts overlapping const int lo_0 = mwf_0->lo; const int hi_0 = mwf_0->hi; @@ -347,6 +270,72 @@ void wavefront_bialign_overlap( /* * Bidirectional breakpoint detection */ +void wavefront_bialign_find_breakpoint_init( + wavefront_aligner_t* const alg_forward, + wavefront_aligner_t* const alg_reverse, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const distance_metric_t distance_metric, + alignment_form_t* const form, + const affine2p_matrix_type component_begin, + const affine2p_matrix_type component_end) { + // Resize wavefront aligner + wavefront_unialign_resize(alg_forward,pattern,pattern_length,text,text_length,false); + wavefront_unialign_resize(alg_reverse,pattern,pattern_length,text,text_length,true); + // Configure form forward and reverse + alignment_span_t span_forward = + (form->pattern_begin_free > 0 || form->text_begin_free > 0) ? alignment_endsfree : alignment_end2end; + alignment_form_t form_forward = { + .span = span_forward, + .pattern_begin_free = form->pattern_begin_free, + .pattern_end_free = 0, + .text_begin_free = form->text_begin_free, + .text_end_free = 0, + }; + alignment_span_t span_reverse = + (form->pattern_end_free > 0 || form->text_end_free > 0) ? alignment_endsfree : alignment_end2end; + alignment_form_t form_reverse = { + .span = span_reverse, + .pattern_begin_free = form->pattern_end_free, + .pattern_end_free = 0, + .text_begin_free = form->text_end_free, + .text_end_free = 0, + }; + // Configure WF-compute function (global) + switch (distance_metric) { + case indel: + case edit: + alg_forward->align_status.wf_align_compute = &wavefront_compute_edit; + break; + case gap_linear: + alg_forward->align_status.wf_align_compute = &wavefront_compute_linear; + break; + case gap_affine: + alg_forward->align_status.wf_align_compute = &wavefront_compute_affine; + break; + case gap_affine_2p: + alg_forward->align_status.wf_align_compute = &wavefront_compute_affine2p; + break; + default: + fprintf(stderr,"[WFA] Distance function not implemented\n"); + exit(1); + break; + } + // Initialize wavefront (forward) + alg_forward->align_status.num_null_steps = 0; + alg_forward->alignment_form = form_forward; + alg_forward->component_begin = component_begin; + alg_forward->component_end = component_end; + wavefront_unialign_initialize_wavefronts(alg_forward,pattern_length,text_length); + // Initialize wavefront (reverse) + alg_reverse->align_status.num_null_steps = 0; + alg_reverse->alignment_form = form_reverse; + alg_reverse->component_begin = component_end; + alg_reverse->component_end = component_begin; + wavefront_unialign_initialize_wavefronts(alg_reverse,pattern_length,text_length); +} int wavefront_bialign_overlap_gopen_adjust( wavefront_aligner_t* const wf_aligner, const distance_metric_t distance_metric) { @@ -364,6 +353,10 @@ int wavefront_bialign_overlap_gopen_adjust( } int wavefront_bialign_find_breakpoint( wavefront_bialigner_t* const bialigner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, const distance_metric_t distance_metric, alignment_form_t* const form, const affine2p_matrix_type component_begin, @@ -373,19 +366,22 @@ int wavefront_bialign_find_breakpoint( // Parameters wavefront_aligner_t* const alg_forward = bialigner->alg_forward; wavefront_aligner_t* const alg_reverse = bialigner->alg_reverse; + // Init bialignment + wavefront_bialign_find_breakpoint_init( + alg_forward,alg_reverse, + pattern,pattern_length,text,text_length, + distance_metric,form,component_begin,component_end); + // DEBUG alignment_system_t* const system = &alg_forward->system; const int verbose = system->verbose; - // Init bialignment - wavefront_bialign_init(bialigner,distance_metric,form,component_begin,component_end,verbose); - // Sequences - wavefront_sequences_t* const sequences = &alg_forward->sequences; - const int text_length = sequences->text_length; - const int pattern_length = sequences->pattern_length; - // Operators - void (*wf_align_compute)(wavefront_aligner_t* const,const int) = bialigner->wf_align_compute; + if (verbose >= 2) { + wavefront_debug_prologue(alg_forward,pattern,pattern_length,text,text_length); + wavefront_debug_prologue(alg_reverse,pattern,pattern_length,text,text_length); + } // Parameters const int max_alignment_score = alg_forward->system.max_alignment_score; const int max_antidiagonal = DPMATRIX_ANTIDIAGONAL(pattern_length,text_length) - 1; // Note: Even removing -1 + void (*wf_align_compute)(wavefront_aligner_t* const,const int) = alg_forward->align_status.wf_align_compute; int score_forward = 0, score_reverse = 0, forward_max_ak = 0, reverse_max_ak = 0; bool end_reached; // Plot @@ -402,7 +398,7 @@ int wavefront_bialign_find_breakpoint( if (end_reached) return alg_reverse->align_status.status; // Compute wavefronts of increasing score until both wavefronts overlap int max_ak = 0; - bool last_wf_forward = false; + bool last_wf_forward; while (true) { // Check close-to-collision if (forward_max_ak + reverse_max_ak >= max_antidiagonal) break; @@ -481,6 +477,10 @@ int wavefront_bialign_find_breakpoint( */ void wavefront_bialign_base( wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, alignment_form_t* const form, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end, @@ -490,15 +490,19 @@ void wavefront_bialign_base( const int verbose = wf_aligner->system.verbose; // Configure alg_subsidiary->alignment_form = *form; - wavefront_unialign_init(alg_subsidiary,component_begin,component_end); + wavefront_unialign_init( + alg_subsidiary,pattern,pattern_length, + text,text_length,component_begin,component_end); // DEBUG - if (verbose >= 2) wavefront_debug_begin(alg_subsidiary); + if (verbose >= 2) { + wavefront_debug_prologue(alg_subsidiary,pattern,pattern_length,text,text_length); + } // Wavefront align sequences wavefront_unialign(alg_subsidiary); wf_aligner->align_status.status = alg_subsidiary->align_status.status; // DEBUG if (verbose >= 2) { - wavefront_debug_end(alg_subsidiary); + wavefront_debug_epilogue(alg_subsidiary); wavefront_debug_check_correct(wf_aligner); } // Append CIGAR @@ -507,6 +511,10 @@ void wavefront_bialign_base( } void wavefront_bialign_exception( wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, alignment_form_t* const form, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end, @@ -516,9 +524,6 @@ void wavefront_bialign_exception( if (align_status == WF_STATUS_MAX_SCORE_REACHED || align_status == WF_STATUS_UNFEASIBLE) { wf_aligner->align_status.status = align_status; - if (align_status == WF_STATUS_MAX_SCORE_REACHED) { - wf_aligner->cigar->score = -wf_aligner->system.max_alignment_score; - } return; } // Check end reached @@ -534,7 +539,9 @@ void wavefront_bialign_exception( } // Fallback if possible if (score_reached <= WF_BIALIGN_FALLBACK_MIN_SCORE) { - wavefront_bialign_base(wf_aligner,form,component_begin,component_end,align_level); + wavefront_bialign_base( + wf_aligner,pattern,pattern_length,text,text_length, + form,component_begin,component_end,align_level); } else { wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; } @@ -577,17 +584,18 @@ void wavefront_bialign_init_half_1( } void wavefront_bialign_alignment( wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_begin, + const int pattern_end, + const char* const text, + const int text_begin, + const int text_end, alignment_form_t* const form, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end, const int score_remaining, const int align_level) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->bialigner->alg_forward->sequences; - const int pattern_begin = sequences->pattern_begin; - const int pattern_end = sequences->pattern_begin + sequences->pattern_length; - const int text_begin = sequences->text_begin; - const int text_end = sequences->text_begin + sequences->text_length; const int pattern_length = pattern_end - pattern_begin; const int text_length = text_end - text_begin; // Trivial cases @@ -600,24 +608,32 @@ void wavefront_bialign_alignment( } // Fall back to regular WFA if (score_remaining <= WF_BIALIGN_FALLBACK_MIN_SCORE) { - wavefront_bialign_base(wf_aligner,form,component_begin,component_end,align_level); + wavefront_bialign_base(wf_aligner, + pattern+pattern_begin,pattern_length, + text+text_begin,text_length, + form,component_begin,component_end,align_level); return; } // Find breakpoint in the alignment wf_bialign_breakpoint_t breakpoint; const int align_status = wavefront_bialign_find_breakpoint( - wf_aligner->bialigner,wf_aligner->penalties.distance_metric, - form,component_begin,component_end,&breakpoint,align_level); + wf_aligner->bialigner, + pattern+pattern_begin,pattern_length, + text+text_begin,text_length, + wf_aligner->penalties.distance_metric, + form,component_begin,component_end, + &breakpoint,align_level); // DEBUG if (wf_aligner->system.verbose >= 2) { - wf_aligner->bialigner->alg_forward->align_status.status = align_status; - wf_aligner->bialigner->alg_reverse->align_status.status = align_status; - wavefront_debug_end(wf_aligner->bialigner->alg_forward); - wavefront_debug_end(wf_aligner->bialigner->alg_reverse); + wavefront_debug_epilogue(wf_aligner->bialigner->alg_forward); + wavefront_debug_epilogue(wf_aligner->bialigner->alg_reverse); } // Check status if (align_status != WF_STATUS_SUCCESSFUL) { - wavefront_bialign_exception(wf_aligner,form,component_begin,component_end,align_level,align_status); + wavefront_bialign_exception(wf_aligner, + pattern+pattern_begin,pattern_length, + text+text_begin,text_length, + form,component_begin,component_end,align_level,align_status); return; } // Breakpoint found @@ -633,11 +649,10 @@ void wavefront_bialign_alignment( plot->offset_v = pattern_begin; plot->offset_h = text_begin; } - wavefront_bialigner_set_sequences_bounds(wf_aligner->bialigner, - pattern_begin,pattern_begin+breakpoint_v, - text_begin,text_begin+breakpoint_h); wavefront_bialign_init_half_0(form,&form_0); wavefront_bialign_alignment(wf_aligner, + pattern,pattern_begin,pattern_begin+breakpoint_v, + text,text_begin,text_begin+breakpoint_h, &form_0,component_begin,breakpoint.component, breakpoint.score_forward,align_level+1); if (wf_aligner->align_status.status != WF_STATUS_SUCCESSFUL) return; @@ -647,11 +662,10 @@ void wavefront_bialign_alignment( plot->offset_v = pattern_begin + breakpoint_v; plot->offset_h = text_begin + breakpoint_h; } - wavefront_bialigner_set_sequences_bounds(wf_aligner->bialigner, - pattern_begin+breakpoint_v,pattern_end, - text_begin+breakpoint_h,text_end); wavefront_bialign_init_half_1(form,&form_1); wavefront_bialign_alignment(wf_aligner, + pattern,pattern_begin+breakpoint_v,pattern_end, + text,text_begin+breakpoint_h,text_end, &form_1,breakpoint.component,component_end, breakpoint.score_reverse,align_level+1); if (wf_aligner->align_status.status != WF_STATUS_SUCCESSFUL) return; @@ -663,28 +677,25 @@ void wavefront_bialign_alignment( * Bidirectional Score-only */ void wavefront_bialign_compute_score( - wavefront_aligner_t* const wf_aligner) { - // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->bialigner->alg_forward->sequences; - const int text_length = sequences->text_length; - const int pattern_length = sequences->pattern_length; + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length) { // Find breakpoint in the alignment wf_bialign_breakpoint_t breakpoint; - const int align_status = wavefront_bialign_find_breakpoint(wf_aligner->bialigner, + const int align_status = wavefront_bialign_find_breakpoint( + wf_aligner->bialigner,pattern,pattern_length,text,text_length, wf_aligner->penalties.distance_metric,&wf_aligner->alignment_form, affine_matrix_M,affine_matrix_M,&breakpoint,0); // DEBUG if (wf_aligner->system.verbose >= 2) { - wavefront_debug_end(wf_aligner->bialigner->alg_forward); - wavefront_debug_end(wf_aligner->bialigner->alg_reverse); + wavefront_debug_epilogue(wf_aligner->bialigner->alg_forward); + wavefront_debug_epilogue(wf_aligner->bialigner->alg_reverse); } // Check status - if (align_status == WF_STATUS_MAX_SCORE_REACHED || - align_status == WF_STATUS_UNFEASIBLE) { + if (align_status == WF_STATUS_MAX_SCORE_REACHED || align_status == WF_STATUS_UNFEASIBLE) { wf_aligner->align_status.status = align_status; - if (align_status == WF_STATUS_MAX_SCORE_REACHED) { - wf_aligner->cigar->score = -wf_aligner->system.max_alignment_score; - } return; } if (align_status == WF_STATUS_END_REACHED) { @@ -706,21 +717,28 @@ void wavefront_bialign_compute_score( * Bidirectional dispatcher */ void wavefront_bialign( - wavefront_aligner_t* const wf_aligner) { + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length) { // Init wf_aligner->align_status.status = WF_STATUS_SUCCESSFUL; // Init OK + // Just for outputting info at plot + wf_aligner->pattern = (char*)pattern; + wf_aligner->pattern_length = pattern_length; + wf_aligner->text = (char*)text; + wf_aligner->text_length = text_length; // Select scope if (wf_aligner->alignment_scope == compute_score) { - wavefront_bialign_compute_score(wf_aligner); + wavefront_bialign_compute_score(wf_aligner,pattern,pattern_length,text,text_length); } else { - // Resize CIGAR - wavefront_sequences_t* const sequences = &wf_aligner->bialigner->alg_forward->sequences; - const int text_length = sequences->text_length; - const int pattern_length = sequences->pattern_length; cigar_resize(wf_aligner->cigar,2*(pattern_length+text_length)); // Bidirectional alignment const bool min_length = MAX(pattern_length,text_length) <= WF_BIALIGN_FALLBACK_MIN_LENGTH; wavefront_bialign_alignment(wf_aligner, + pattern,0,pattern_length, + text,0,text_length, &wf_aligner->alignment_form, affine_matrix_M,affine_matrix_M, min_length ? 0 : INT_MAX,0); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h index 7a96a0d6..f13eec6a 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h @@ -37,6 +37,10 @@ * Bidirectional WFA */ void wavefront_bialign( - wavefront_aligner_t* const wf_aligner); + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length); #endif /* WAVEFRONT_BIALIGN_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c index dedc16ec..260379ee 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c @@ -49,6 +49,8 @@ wavefront_bialigner_t* wavefront_bialigner_new( subsidiary_attr.linear_penalties = attributes->linear_penalties; subsidiary_attr.affine_penalties = attributes->affine_penalties; subsidiary_attr.affine2p_penalties = attributes->affine2p_penalties; + subsidiary_attr.match_funct = attributes->match_funct; + subsidiary_attr.match_funct_arguments = attributes->match_funct_arguments; // Set specifics for subsidiary aligners subsidiary_attr.heuristic = attributes->heuristic; // Inherit same heuristic subsidiary_attr.memory_mode = wavefront_memory_high; // Classic WFA @@ -83,70 +85,6 @@ void wavefront_bialigner_delete( wavefront_aligner_delete(wf_bialigner->alg_subsidiary); free(wf_bialigner); } -/* - * Sequences - */ -void wavefront_bialigner_set_sequences_ascii( - wavefront_bialigner_t* const wf_bialigner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length) { - wavefront_sequences_init_ascii( - &wf_bialigner->alg_forward->sequences, - pattern,pattern_length,text,text_length,false); - wavefront_sequences_init_ascii( - &wf_bialigner->alg_reverse->sequences, - pattern,pattern_length,text,text_length,true); - wavefront_sequences_init_ascii( - &wf_bialigner->alg_subsidiary->sequences, - pattern,pattern_length,text,text_length,false); -} -void wavefront_bialigner_set_sequences_lambda( - wavefront_bialigner_t* const wf_bialigner, - alignment_match_funct_t match_funct, - void* match_funct_arguments, - const int pattern_length, - const int text_length) { - wavefront_sequences_init_lambda(&wf_bialigner->alg_forward->sequences, - match_funct,match_funct_arguments,pattern_length,text_length,false); - wavefront_sequences_init_lambda(&wf_bialigner->alg_reverse->sequences, - match_funct,match_funct_arguments,pattern_length,text_length,true); - wavefront_sequences_init_lambda(&wf_bialigner->alg_subsidiary->sequences, - match_funct,match_funct_arguments,pattern_length,text_length,false); -} -void wavefront_bialigner_set_sequences_packed2bits( - wavefront_bialigner_t* const wf_bialigner, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length) { - wavefront_sequences_init_packed2bits( - &wf_bialigner->alg_forward->sequences, - pattern,pattern_length,text,text_length,false); - wavefront_sequences_init_packed2bits( - &wf_bialigner->alg_reverse->sequences, - pattern,pattern_length,text,text_length,true); - wavefront_sequences_init_packed2bits( - &wf_bialigner->alg_subsidiary->sequences, - pattern,pattern_length,text,text_length,false); -} -void wavefront_bialigner_set_sequences_bounds( - wavefront_bialigner_t* const wf_bialigner, - const int pattern_begin, - const int pattern_end, - const int text_begin, - const int text_end) { - wavefront_sequences_set_bounds( - &wf_bialigner->alg_forward->sequences, - pattern_begin,pattern_end,text_begin,text_end); - wavefront_sequences_set_bounds( - &wf_bialigner->alg_reverse->sequences, - pattern_begin,pattern_end,text_begin,text_end); - wavefront_sequences_set_bounds( - &wf_bialigner->alg_subsidiary->sequences, - pattern_begin,pattern_end,text_begin,text_end); -} /* * Accessors */ @@ -163,6 +101,17 @@ void wavefront_bialigner_set_heuristic( wf_bialigner->alg_reverse->heuristic = *heuristic; wf_bialigner->alg_subsidiary->heuristic = *heuristic; } +void wavefront_bialigner_set_match_funct( + wavefront_bialigner_t* const wf_bialigner, + int (*match_funct)(int,int,void*), + void* const match_funct_arguments) { + wf_bialigner->alg_forward->match_funct = match_funct; + wf_bialigner->alg_forward->match_funct_arguments = match_funct_arguments; + wf_bialigner->alg_reverse->match_funct = match_funct; + wf_bialigner->alg_reverse->match_funct_arguments = match_funct_arguments; + wf_bialigner->alg_subsidiary->match_funct = match_funct; + wf_bialigner->alg_subsidiary->match_funct_arguments = match_funct_arguments; +} void wavefront_bialigner_set_max_alignment_score( wavefront_bialigner_t* const wf_bialigner, const int max_alignment_score) { @@ -182,16 +131,16 @@ void wavefront_bialigner_set_max_memory( wf_bialigner->alg_subsidiary->system.max_memory_abort = max_memory_abort; } void wavefront_bialigner_set_max_num_threads( - wavefront_bialigner_t* const wf_bialigner, - const int max_num_threads) { - wf_bialigner->alg_forward->system.max_num_threads = max_num_threads; - wf_bialigner->alg_reverse->system.max_num_threads = max_num_threads; - wf_bialigner->alg_subsidiary->system.max_num_threads = max_num_threads; + wavefront_bialigner_t* const wf_bialigner, + const int max_num_threads) { + wf_bialigner->alg_forward->system.max_num_threads = max_num_threads; + wf_bialigner->alg_reverse->system.max_num_threads = max_num_threads; + wf_bialigner->alg_subsidiary->system.max_num_threads = max_num_threads; } void wavefront_bialigner_set_min_offsets_per_thread( - wavefront_bialigner_t* const wf_bialigner, - const int min_offsets_per_thread) { - wf_bialigner->alg_forward->system.min_offsets_per_thread = min_offsets_per_thread; - wf_bialigner->alg_reverse->system.min_offsets_per_thread = min_offsets_per_thread; - wf_bialigner->alg_subsidiary->system.min_offsets_per_thread = min_offsets_per_thread; + wavefront_bialigner_t* const wf_bialigner, + const int min_offsets_per_thread) { + wf_bialigner->alg_forward->system.min_offsets_per_thread = min_offsets_per_thread; + wf_bialigner->alg_reverse->system.min_offsets_per_thread = min_offsets_per_thread; + wf_bialigner->alg_subsidiary->system.min_offsets_per_thread = min_offsets_per_thread; } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h index 81601a34..e5781b22 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h @@ -35,7 +35,6 @@ #include "wavefront_attributes.h" #include "wavefront_heuristic.h" #include "wavefront_offset.h" -#include "wavefront_sequences.h" // Wavefront ahead definition typedef struct _wavefront_aligner_t wavefront_aligner_t; @@ -54,12 +53,9 @@ typedef struct { } wf_bialign_breakpoint_t; typedef struct { - // Wavefronts wavefront_aligner_t* alg_forward; // Forward aligner wavefront_aligner_t* alg_reverse; // Reverse aligner wavefront_aligner_t* alg_subsidiary; // Subsidiary aligner - // Operators - void (*wf_align_compute)(wavefront_aligner_t* const,const int); } wavefront_bialigner_t; /* @@ -73,34 +69,6 @@ void wavefront_bialigner_reap( void wavefront_bialigner_delete( wavefront_bialigner_t* const wf_bialigner); -/* - * Sequences - */ -void wavefront_bialigner_set_sequences_ascii( - wavefront_bialigner_t* const wf_bialigner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length); -void wavefront_bialigner_set_sequences_lambda( - wavefront_bialigner_t* const wf_bialigner, - alignment_match_funct_t match_funct, - void* match_funct_arguments, - const int pattern_length, - const int text_length); -void wavefront_bialigner_set_sequences_packed2bits( - wavefront_bialigner_t* const wf_bialigner, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length); -void wavefront_bialigner_set_sequences_bounds( - wavefront_bialigner_t* const wf_bialigner, - const int pattern_begin, - const int pattern_end, - const int text_begin, - const int text_end); - /* * Accessors */ @@ -109,6 +77,10 @@ uint64_t wavefront_bialigner_get_size( void wavefront_bialigner_set_heuristic( wavefront_bialigner_t* const wf_bialigner, wavefront_heuristic_t* const heuristic); +void wavefront_bialigner_set_match_funct( + wavefront_bialigner_t* const wf_bialigner, + int (*match_funct)(int,int,void*), + void* const match_funct_arguments); void wavefront_bialigner_set_max_alignment_score( wavefront_bialigner_t* const wf_bialigner, const int max_alignment_score); @@ -120,6 +92,6 @@ void wavefront_bialigner_set_max_num_threads( wavefront_bialigner_t* const wf_bialigner, const int max_num_threads); void wavefront_bialigner_set_min_offsets_per_thread( - wavefront_bialigner_t* const wf_bialigner, - const int min_offsets_per_thread); + wavefront_bialigner_t* const wf_bialigner, + const int min_offsets_per_thread); #endif /* WAVEFRONT_BIALIGNER_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c index 45a5f1a1..8ba5ca33 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "system/mm_allocator.h" +#include "utils/string_padded.h" #include "alignment/affine2p_penalties.h" #include "wavefront_compute.h" @@ -570,9 +571,8 @@ void wavefront_compute_trim_ends( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; wf_offset_t* const offsets = wavefront->offsets; // Trim from hi int k; @@ -651,4 +651,3 @@ void wavefront_compute_thread_limits( *thread_hi = t_hi; } #endif - diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c index c093a4e6..d90390a9 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "system/mm_allocator.h" +#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_backtrace_offload.h" @@ -47,9 +48,8 @@ void wavefront_compute_affine_idm( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -93,9 +93,8 @@ void wavefront_compute_affine_idm_piggyback( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -258,5 +257,3 @@ void wavefront_compute_affine( // Process wavefront ends wavefront_compute_process_ends(wf_aligner,&wavefront_set,score); } - - diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c index 14b4bb1b..2a1a3701 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "system/mm_allocator.h" +#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_compute_affine.h" #include "wavefront_backtrace_offload.h" @@ -48,9 +49,8 @@ void wavefront_compute_affine2p_idm( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -113,9 +113,8 @@ void wavefront_compute_affine2p_idm_piggyback( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -366,4 +365,3 @@ void wavefront_compute_affine2p( // Process wavefront ends wavefront_compute_process_ends(wf_aligner,&wavefront_set,score); } - diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c index 13202a05..1eedcfb9 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "system/mm_allocator.h" +#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_backtrace_offload.h" @@ -48,9 +49,8 @@ void wavefront_compute_indel_idm( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; const wf_offset_t* const prev_offsets = wf_prev->offsets; wf_offset_t* const curr_offsets = wf_curr->offsets; // Compute-Next kernel loop @@ -76,9 +76,8 @@ void wavefront_compute_edit_idm( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; const wf_offset_t* const prev_offsets = wf_prev->offsets; wf_offset_t* const curr_offsets = wf_curr->offsets; // Compute-Next kernel loop @@ -109,9 +108,8 @@ void wavefront_compute_indel_idm_piggyback( const int hi, const int score) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // Previous WF const wf_offset_t* const prev_offsets = wf_prev->offsets; const pcigar_t* const prev_pcigar = wf_prev->bt_pcigar; @@ -152,9 +150,8 @@ void wavefront_compute_edit_idm_piggyback( const int hi, const int score) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // Previous WF const wf_offset_t* const prev_offsets = wf_prev->offsets; const pcigar_t* const prev_pcigar = wf_prev->bt_pcigar; @@ -220,9 +217,8 @@ void wavefront_compute_edit_exact_prune( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int plen = sequences->pattern_length; - const int tlen = sequences->text_length; + const int plen = wf_aligner->pattern_length; + const int tlen = wf_aligner->text_length; wf_offset_t* const offsets = wavefront->offsets; const int lo = wavefront->lo; const int hi = wavefront->hi; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c index d9c1aa7b..3206fbf7 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "system/mm_allocator.h" +#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_backtrace_offload.h" @@ -47,9 +48,8 @@ void wavefront_compute_linear_idm( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -81,9 +81,8 @@ void wavefront_compute_linear_idm_piggyback( const int lo, const int hi) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // In M const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const pcigar_t* const m_misms_bt_pcigar = wavefront_set->in_mwavefront_misms->bt_pcigar; @@ -193,5 +192,3 @@ void wavefront_compute_linear( // Process wavefront ends wavefront_compute_process_ends(wf_aligner,&wavefront_set,score); } - - diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c index 8782b868..41425a8d 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c @@ -41,12 +41,13 @@ bool wavefront_check_alignment( FILE* const stream, wavefront_aligner_t* const wf_aligner) { // Parameters - wavefront_sequences_t* const sequences = (wf_aligner->bialigner==NULL) ? - &wf_aligner->sequences : &wf_aligner->bialigner->alg_forward->sequences; - const char* const pattern = sequences->pattern_buffer; - const int pattern_length = sequences->pattern_buffer_length; - const char* const text = sequences->text_buffer; - const int text_length = sequences->text_buffer_length; + const char* const pattern = wf_aligner->pattern; + const int pattern_length = wf_aligner->pattern_length; + const char* const text = wf_aligner->text; + const int text_length = wf_aligner->text_length; + // Custom function to compare sequences + alignment_match_funct_t match_funct = wf_aligner->match_funct; + void* match_funct_arguments = wf_aligner->match_funct_arguments; // CIGAR cigar_t* const cigar = wf_aligner->cigar; char* const operations = cigar->operations; @@ -59,15 +60,14 @@ bool wavefront_check_alignment( switch (operations[i]) { case 'M': { // Check match - if (sequences->mode != wf_sequences_lambda) { - const bool is_match = (pattern[pattern_pos]==text[text_pos]); - if (!is_match) { - fprintf(stream,"[WFA::Check] Alignment not matching (pattern[%d]=%c != text[%d]=%c)\n", - pattern_pos,pattern[pattern_pos], - text_pos,text[text_pos]); - alignment_correct = false; - break; - } + const bool is_match = (match_funct!=NULL) ? + match_funct(pattern_pos,text_pos,match_funct_arguments) : + pattern[pattern_pos] == text[text_pos]; + if (!is_match) { + fprintf(stream,"[WFA::Check] Alignment not matching (pattern[%d]=%c != text[%d]=%c)\n", + pattern_pos,pattern[pattern_pos],text_pos,text[text_pos]); + alignment_correct = false; + break; } ++pattern_pos; ++text_pos; @@ -75,15 +75,14 @@ bool wavefront_check_alignment( } case 'X': { // Check mismatch - if (sequences->mode != wf_sequences_lambda) { - const bool is_match = (pattern[pattern_pos]==text[text_pos]); - if (is_match) { - fprintf(stream,"[WFA::Check] Alignment not mismatching (pattern[%d]=%c == text[%d]=%c)\n", - pattern_pos,pattern[pattern_pos], - text_pos,text[text_pos]); - alignment_correct = false; - break; - } + const bool is_match = (match_funct!=NULL) ? + match_funct(pattern_pos,text_pos,match_funct_arguments) : + pattern[pattern_pos] == text[text_pos]; + if (is_match) { + fprintf(stream,"[WFA::Check] Alignment not mismatching (pattern[%d]=%c == text[%d]=%c)\n", + pattern_pos,pattern[pattern_pos],text_pos,text[text_pos]); + alignment_correct = false; + break; } ++pattern_pos; ++text_pos; @@ -124,80 +123,121 @@ void wavefront_report_lite( FILE* const stream, wavefront_aligner_t* const wf_aligner) { // Parameters - wavefront_sequences_t* const sequences = (wf_aligner->bialigner==NULL) ? - &wf_aligner->sequences : &wf_aligner->bialigner->alg_subsidiary->sequences; - const char* const pattern = sequences->pattern; - const int pattern_length = sequences->pattern_length; - const char* const text = sequences->text; - const int text_length = sequences->text_length; + const char* const pattern = wf_aligner->pattern; + const int pattern_length = wf_aligner->pattern_length; + const char* const text = wf_aligner->text; + const int text_length = wf_aligner->text_length; const int status = wf_aligner->align_status.status; const uint64_t memory_used = wf_aligner->align_status.memory_used; - // BANNER (#0) + // Banner fprintf(stream,"[WFA::Debug]"); - // SCORE (#1) - // const int score = wavefront_compute_classic_score( - // wf_aligner,pattern_length,text_length,wf_aligner->cigar->score); - const int score = wf_aligner->cigar->score; - fprintf(stream,"\t%d",(score==INT32_MIN) ? -1 : score); - // PATTERN_LENGTH (#2) - fprintf(stream,"\t%d",pattern_length); - // TEXT_LENGTH (#3) - fprintf(stream,"\t%d",text_length); - // STATUS (#4) - fprintf(stream,"\t%s",wavefront_align_strerror_short(status)); - // TIME (#5) + // Sequences + const int score = wavefront_compute_classic_score( + wf_aligner,wf_aligner->pattern_length, + wf_aligner->text_length,wf_aligner->cigar->score); + fprintf(stream,"\t%d",score); + fprintf(stream,"\t%d\t%d",pattern_length,text_length); + fprintf(stream,"\t%s",(status==0) ? "OK" : "FAIL"); fprintf(stream,"\t%2.3f",TIMER_GET_TOTAL_MS(&wf_aligner->system.timer)); - // MEMORY (#6) fprintf(stream,"\t%luMB\t",CONVERT_B_TO_MB(memory_used)); - // ATTRIBUTES (#7) fprintf(stream,"["); - fprintf(stream,"%d",wf_aligner->align_status.status); - fprintf(stream,";"); - wavefront_aligner_print_mode(stream,wf_aligner); - fprintf(stream,";"); + wavefront_aligner_print_type(stream,wf_aligner); + fprintf(stream,","); wavefront_aligner_print_scope(stream,wf_aligner); - fprintf(stream,";"); + fprintf(stream,","); wavefront_penalties_print(stream,&wf_aligner->penalties); - fprintf(stream,";"); - wavefront_aligner_print_conf(stream,wf_aligner); - fprintf(stream,";"); - wavefront_heuristic_print(stream,&wf_aligner->heuristic); - fprintf(stream,";"); - fprintf(stream,"(%d,%d,%d)", - wf_aligner->wf_components.num_wavefronts, - wf_aligner->wf_components.historic_min_lo, - wf_aligner->wf_components.historic_max_hi); fprintf(stream,"]\t"); - // CIGAR (#8) - if (cigar_is_null(wf_aligner->cigar)) { - fprintf(stream,"-"); - } else { - cigar_print(stream,wf_aligner->cigar,true); - } - // SEQUENCES (#9 #10) - if (sequences->mode == wf_sequences_lambda) { + cigar_print(stream,wf_aligner->cigar,true); + if (wf_aligner->match_funct != NULL) { fprintf(stream,"\t-\t-"); } else { fprintf(stream,"\t%.*s\t%.*s",pattern_length,pattern,text_length,text); } fprintf(stream,"\n"); } +void wavefront_report_verbose_begin( + FILE* const stream, + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length) { + // Input sequences + fprintf(stream,"[WFA::Report::Begin] ["); + wavefront_aligner_print_type(stream,wf_aligner); + fprintf(stream,"]-Alignment (obj=%p)\n",wf_aligner); + if (wf_aligner->match_funct != NULL) { + fprintf(stream,"[WFA::Report]\tPattern\t%d\tcustom-funct()\n",pattern_length); + fprintf(stream,"[WFA::Report]\tText\t%d\tcustom-funct()\n",text_length); + } else { + fprintf(stream,"[WFA::Report]\tPattern\t%d\t%.*s\n",pattern_length,pattern_length,pattern); + fprintf(stream,"[WFA::Report]\tText\t%d\t%.*s\n",text_length,text_length,text); + } + // Alignment scope/form + fprintf(stream,"[WFA::Report]\tScope="); + wavefront_aligner_print_scope(stream,wf_aligner); + fprintf(stream," Max-score=%d", + wf_aligner->system.max_alignment_score); + // Penalties + fprintf(stream," Penalties="); + wavefront_penalties_print(stream,&wf_aligner->penalties); + // Heuristic + fprintf(stream," Heuristic="); + wavefront_heuristic_print(stream,&wf_aligner->heuristic); + // Memory mode + fprintf(stream," Memory.mode=(%d,%luMB,%luMB,%luMB)\n", + wf_aligner->memory_mode, + CONVERT_B_TO_MB(wf_aligner->system.max_memory_compact), + CONVERT_B_TO_MB(wf_aligner->system.max_memory_resident), + CONVERT_B_TO_MB(wf_aligner->system.max_memory_abort)); +} +void wavefront_report_verbose_end( + FILE* const stream, + wavefront_aligner_t* const wf_aligner) { + // Finish report + fprintf(stream,"[WFA::Report::End]\tFinish.status=%d",wf_aligner->align_status.status); + fprintf(stream," Time.taken="); + timer_print_total(stream,&wf_aligner->system.timer); + fprintf(stream," Memory.used=%luMB", + CONVERT_B_TO_MB(wf_aligner->align_status.memory_used)); + fprintf(stream," WFA.components=(wfs=%d,maxlo=%d,maxhi=%d)", + wf_aligner->wf_components.num_wavefronts, + wf_aligner->wf_components.historic_min_lo, + wf_aligner->wf_components.historic_max_hi); + const int score = wavefront_compute_classic_score( + wf_aligner,wf_aligner->pattern_length, + wf_aligner->text_length,wf_aligner->cigar->score); + fprintf(stream," WFA.score=%d",score); + fprintf(stream," WFA.cigar="); + cigar_print(stream,wf_aligner->cigar,true); + fprintf(stream,"\n"); +} /* * Debug */ -void wavefront_debug_begin( - wavefront_aligner_t* const wf_aligner) { +void wavefront_debug_prologue( + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length) { // Check verbose level if (wf_aligner->system.verbose >= 1) { - timer_reset(&wf_aligner->system.timer); timer_start(&wf_aligner->system.timer); + if (wf_aligner->system.verbose >= 4) { + wavefront_report_verbose_begin(stderr,wf_aligner, + pattern,pattern_length,text,text_length); + } } } -void wavefront_debug_end( +void wavefront_debug_epilogue( wavefront_aligner_t* const wf_aligner) { // Print Summary if (wf_aligner->system.verbose >= 1) { timer_stop(&wf_aligner->system.timer); + if (wf_aligner->system.verbose >= 4) { + wavefront_report_verbose_end(stderr,wf_aligner); + } wavefront_report_lite(stderr,wf_aligner); } } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h index 828343af..1bdb8532 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h @@ -37,9 +37,13 @@ /* * Debug */ -void wavefront_debug_begin( - wavefront_aligner_t* const wf_aligner); -void wavefront_debug_end( +void wavefront_debug_prologue( + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length); +void wavefront_debug_epilogue( wavefront_aligner_t* const wf_aligner); /* diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c index 21e7b3f2..945f278b 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c @@ -26,69 +26,285 @@ * * PROJECT: Wavefront Alignment Algorithms * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module for the "extension" of exact matches + * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches */ #include "utils/commons.h" #include "system/mm_allocator.h" +#include "utils/string_padded.h" #include "wavefront_extend.h" -#include "wavefront_extend_kernels.h" +#include "wavefront_align.h" #include "wavefront_compute.h" -#include "wavefront_termination.h" +#include "wavefront_heuristic.h" #ifdef WFA_PARALLEL #include #endif /* - * Wavefront Extension (End-to-end) + * Termination (detect end of alignment) */ -void wavefront_extend_end2end_dispatcher_seq( +bool wavefront_extend_end2end_check_termination( wavefront_aligner_t* const wf_aligner, wavefront_t* const mwavefront, const int score, - const int lo, - const int hi) { + const int score_mod) { // Parameters - wavefront_sequences_t* const seqs = &wf_aligner->sequences; - // Check the sequence mode - if (seqs->mode == wf_sequences_ascii) { - wavefront_extend_matches_packed_end2end(wf_aligner,mwavefront,lo,hi); - } else { - wf_offset_t dummy; - wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,false,&dummy); + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; + const affine2p_matrix_type component_end = wf_aligner->component_end; + const int alignment_k = DPMATRIX_DIAGONAL(text_length,pattern_length); + const wf_offset_t alignment_offset = DPMATRIX_OFFSET(text_length,pattern_length); + // Select end component + switch (component_end) { + case affine2p_matrix_M: { + // Check diagonal/offset + if (mwavefront->lo > alignment_k || alignment_k > mwavefront->hi) return false; // Not done + const wf_offset_t moffset = mwavefront->offsets[alignment_k]; + if (moffset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_I1: { + // Fetch I1-wavefront & check diagonal/offset + wavefront_t* const i1wavefront = wf_aligner->wf_components.i1wavefronts[score_mod]; + if (i1wavefront == NULL || i1wavefront->lo > alignment_k || alignment_k > i1wavefront->hi) return false; // Not done + const wf_offset_t i1offset = i1wavefront->offsets[alignment_k]; + if (i1offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_I2: { + // Fetch I2-wavefront & check diagonal/offset + wavefront_t* const i2wavefront = wf_aligner->wf_components.i2wavefronts[score_mod]; + if (i2wavefront == NULL || i2wavefront->lo > alignment_k || alignment_k > i2wavefront->hi) return false; // Not done + const wf_offset_t i2offset = i2wavefront->offsets[alignment_k]; + if (i2offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_D1: { + // Fetch D1-wavefront & check diagonal/offset + wavefront_t* const d1wavefront = wf_aligner->wf_components.d1wavefronts[score_mod]; + if (d1wavefront == NULL || d1wavefront->lo > alignment_k || alignment_k > d1wavefront->hi) return false; // Not done + const wf_offset_t d1offset = d1wavefront->offsets[alignment_k]; + if (d1offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_D2: { + // Fetch D2-wavefront & check diagonal/offset + wavefront_t* const d2wavefront = wf_aligner->wf_components.d2wavefronts[score_mod]; + if (d2wavefront == NULL || d2wavefront->lo > alignment_k || alignment_k > d2wavefront->hi) return false; // Not done + const wf_offset_t d2offset = d2wavefront->offsets[alignment_k]; + if (d2offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + default: + break; } + return false; } -void wavefront_extend_end2end_dispatcher_threads( +bool wavefront_extend_endsfree_check_termination( wavefront_aligner_t* const wf_aligner, wavefront_t* const mwavefront, - const int score) { + const int score, + const int k, + const wf_offset_t offset) { // Parameters - const int lo = mwavefront->lo; - const int hi = mwavefront->hi; - const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); - if (num_threads == 1) { - // Extend wavefront single-thread - wavefront_extend_end2end_dispatcher_seq(wf_aligner,mwavefront,score,lo,hi); - } else { -#ifdef WFA_PARALLEL - // Extend wavefront in parallel - #pragma omp parallel num_threads(num_threads) - { - int t_lo, t_hi; - wavefront_compute_thread_limits(omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - wavefront_extend_end2end_dispatcher_seq(wf_aligner,mwavefront,score,t_lo,t_hi); + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; + // Check ends-free reaching boundaries + const int h_pos = WAVEFRONT_H(k,offset); + const int v_pos = WAVEFRONT_V(k,offset); + if (h_pos >= text_length) { // Text is aligned + // Is Pattern end-free? + const int pattern_left = pattern_length - v_pos; + const int pattern_end_free = wf_aligner->alignment_form.pattern_end_free; + if (pattern_left <= pattern_end_free) { + #ifdef WFA_PARALLEL + #pragma omp critical + #endif + { + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = k; + wf_aligner->alignment_end_pos.offset = offset; + } + return true; // Quit (we are done) } -#endif } + if (v_pos >= pattern_length) { // Pattern is aligned + // Is text end-free? + const int text_left = text_length - h_pos; + const int text_end_free = wf_aligner->alignment_form.text_end_free; + if (text_left <= text_end_free) { + #ifdef WFA_PARALLEL + #pragma omp critical + #endif + { + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = k; + wf_aligner->alignment_end_pos.offset = offset; + } + return true; // Quit (we are done) + } + } + // Not done + return false; } -int wavefront_extend_end2end( +/* + * Extend kernel + */ +FORCE_INLINE wf_offset_t wavefront_extend_matches_packed_kernel( wavefront_aligner_t* const wf_aligner, - const int score) { + const int k, + wf_offset_t offset) { + // Fetch pattern/text blocks + uint64_t* pattern_blocks = (uint64_t*)(wf_aligner->pattern+WAVEFRONT_V(k,offset)); + uint64_t* text_blocks = (uint64_t*)(wf_aligner->text+WAVEFRONT_H(k,offset)); + // Compare 64-bits blocks + uint64_t cmp = *pattern_blocks ^ *text_blocks; + while (__builtin_expect(cmp==0,0)) { + // Increment offset (full block) + offset += 8; + // Next blocks + ++pattern_blocks; + ++text_blocks; + // Compare + cmp = *pattern_blocks ^ *text_blocks; + } + // Count equal characters + const int equal_right_bits = __builtin_ctzl(cmp); + const int equal_chars = DIV_FLOOR(equal_right_bits,8); + offset += equal_chars; + // Return extended offset + return offset; +} +/* + * Wavefront offset extension comparing characters + * Remember: + * - No offset is out of boundaries !(h>tlen,v>plen) + * - if (h==tlen,v==plen) extension won't increment (sentinels) + */ +FORCE_NO_INLINE void wavefront_extend_matches_packed_end2end( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi) { + wf_offset_t* const offsets = mwavefront->offsets; + int k; + for (k=lo;k<=hi;++k) { + // Fetch offset + const wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Extend offset + offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); + } +} +FORCE_NO_INLINE wf_offset_t wavefront_extend_matches_packed_max( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi) { + wf_offset_t* const offsets = mwavefront->offsets; + wf_offset_t max_antidiag = 0; + int k; + for (k=lo;k<=hi;++k) { + // Fetch offset + const wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Extend offset + offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); + // Compute max + const wf_offset_t antidiag = WAVEFRONT_ANTIDIAGONAL(k,offsets[k]); + if (max_antidiag < antidiag) max_antidiag = antidiag; + } + return max_antidiag; +} +FORCE_NO_INLINE bool wavefront_extend_matches_packed_endsfree( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi) { + wf_offset_t* const offsets = mwavefront->offsets; + int k; + for (k=lo;k<=hi;++k) { + // Fetch offset + wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Extend offset + offset = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); + offsets[k] = offset; + // Check ends-free reaching boundaries + if (wavefront_extend_endsfree_check_termination(wf_aligner,mwavefront,score,k,offset)) { + return true; // Quit (we are done) + } + } + // Alignment not finished + return false; +} +bool wavefront_extend_matches_custom( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi, + const bool endsfree) { + // Parameters (custom matching function) + alignment_match_funct_t match_funct = wf_aligner->match_funct; + void* const func_arguments = wf_aligner->match_funct_arguments; + // Extend diagonally each wavefront point + wf_offset_t* const offsets = mwavefront->offsets; + int k; + for (k=lo;k<=hi;++k) { + // Check offset + wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Count equal characters + int v = WAVEFRONT_V(k,offset); + int h = WAVEFRONT_H(k,offset); + while (match_funct(v,h,func_arguments)) { + h++; v++; offset++; + } + // Update offset + offsets[k] = offset; + // Check ends-free reaching boundaries + if (endsfree && wavefront_extend_endsfree_check_termination(wf_aligner,mwavefront,score,k,offset)) { + return true; // Quit (we are done) + } + } + // Alignment not finished + return false; +} +/* + * Wavefront exact "extension" + */ +int wavefront_extend_end2end_max( + wavefront_aligner_t* const wf_aligner, + const int score, + int* const max_antidiagonal) { // Compute score const bool memory_modular = wf_aligner->wf_components.memory_modular; const int max_score_scope = wf_aligner->wf_components.max_score_scope; const int score_mod = (memory_modular) ? score % max_score_scope : score; + *max_antidiagonal = 0; // Init // Fetch m-wavefront wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; if (mwavefront == NULL) { @@ -100,84 +316,57 @@ int wavefront_extend_end2end( } return 0; // Not done } - // Extend (dispatcher) - wavefront_extend_end2end_dispatcher_threads(wf_aligner,mwavefront,score); - const bool end_reached = wavefront_termination_end2end(wf_aligner,mwavefront,score,score_mod); - if (end_reached) { - wf_aligner->align_status.status = WF_STATUS_END_REACHED; - wf_aligner->align_status.score = score; - return 1; // Done - } - // Cut-off wavefront heuristically - if (wf_aligner->heuristic.strategy != wf_heuristic_none) { - wavefront_heuristic_cufoff(wf_aligner,score,score_mod); - } - return 0; // Not done -} -/* - * Wavefront Extension (End-to-end + MAX-antidiagonal) - */ -wf_offset_t wavefront_extend_end2end_max_dispatcher_seq( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi) { - // Parameters - wavefront_sequences_t* const seqs = &wf_aligner->sequences; - // Check the sequence mode - if (seqs->mode == wf_sequences_ascii) { - return wavefront_extend_matches_packed_end2end_max(wf_aligner,mwavefront,lo,hi); - } else { - wf_offset_t max_antidiag; - wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,false,&max_antidiag); - return max_antidiag; - } -} -wf_offset_t wavefront_extend_end2end_max_dispatcher_threads( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score) { - // Parameters + // Multithreading dispatcher const int lo = mwavefront->lo; const int hi = mwavefront->hi; wf_offset_t max_antidiag = 0; - // Select number of threads const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); if (num_threads == 1) { - // Extend wavefront single-thread - max_antidiag = wavefront_extend_end2end_max_dispatcher_seq(wf_aligner,mwavefront,score,lo,hi); + // Extend wavefront + max_antidiag = wavefront_extend_matches_packed_max(wf_aligner,mwavefront,lo,hi); } else { - // Extend wavefront in parallel #ifdef WFA_PARALLEL + // Extend wavefront in parallel #pragma omp parallel num_threads(num_threads) { int t_lo, t_hi; - wavefront_compute_thread_limits(omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - wf_offset_t t_max_antidiag = wavefront_extend_end2end_max_dispatcher_seq(wf_aligner,mwavefront,score,t_lo,t_hi); + wavefront_compute_thread_limits( + omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + wf_offset_t t_max_antidiag = wavefront_extend_matches_packed_max(wf_aligner,mwavefront,t_lo,t_hi); + #ifdef WFA_PARALLEL #pragma omp critical + #endif { if (t_max_antidiag > max_antidiag) max_antidiag = t_max_antidiag; } } #endif } - // Return maximum antidiagonal - return max_antidiag; + // Check end-to-end finished + const bool end_reached = wavefront_extend_end2end_check_termination(wf_aligner,mwavefront,score,score_mod); + if (end_reached) { + wf_aligner->align_status.status = WF_STATUS_END_REACHED; + wf_aligner->align_status.score = score; + return 1; // Done + } + // Cut-off wavefront heuristically + if (wf_aligner->heuristic.strategy != wf_heuristic_none) { + wavefront_heuristic_cufoff(wf_aligner,score,score_mod); + } + *max_antidiagonal = max_antidiag; + return 0; // Not done } -int wavefront_extend_end2end_max( +int wavefront_extend_end2end( wavefront_aligner_t* const wf_aligner, - const int score, - int* const max_antidiagonal) { + const int score) { // Compute score const bool memory_modular = wf_aligner->wf_components.memory_modular; const int max_score_scope = wf_aligner->wf_components.max_score_scope; const int score_mod = (memory_modular) ? score % max_score_scope : score; - *max_antidiagonal = 0; // Init // Fetch m-wavefront wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; if (mwavefront == NULL) { - // Check alignment feasibility (heuristic variants that can lead to no solution) + // Check alignment feasibility (for heuristic variants that can lead to no solution) if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; wf_aligner->align_status.score = score; @@ -185,9 +374,28 @@ int wavefront_extend_end2end_max( } return 0; // Not done } - // Extend (dispatcher) - const wf_offset_t max_ak = wavefront_extend_end2end_max_dispatcher_threads(wf_aligner,mwavefront,score); - const bool end_reached = wavefront_termination_end2end(wf_aligner,mwavefront,score,score_mod); + // Multithreading dispatcher + const int lo = mwavefront->lo; + const int hi = mwavefront->hi; + bool end_reached = false; + const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); + if (num_threads == 1) { + // Extend wavefront + wavefront_extend_matches_packed_end2end(wf_aligner,mwavefront,lo,hi); + } else { +#ifdef WFA_PARALLEL + // Extend wavefront in parallel + #pragma omp parallel num_threads(num_threads) + { + int t_lo, t_hi; + wavefront_compute_thread_limits( + omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + wavefront_extend_matches_packed_end2end(wf_aligner,mwavefront,t_lo,t_hi); + } +#endif + } + // Check end-to-end finished + end_reached = wavefront_extend_end2end_check_termination(wf_aligner,mwavefront,score,score_mod); if (end_reached) { wf_aligner->align_status.status = WF_STATUS_END_REACHED; wf_aligner->align_status.score = score; @@ -197,67 +405,70 @@ int wavefront_extend_end2end_max( if (wf_aligner->heuristic.strategy != wf_heuristic_none) { wavefront_heuristic_cufoff(wf_aligner,score,score_mod); } - *max_antidiagonal = max_ak; return 0; // Not done } -/* - * Wavefront Extension (Ends-free) - */ -bool wavefront_extend_endsfree_dispatcher_seq( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi) { - // Parameters - wavefront_sequences_t* const seqs = &wf_aligner->sequences; - // Check the sequence mode - if (seqs->mode == wf_sequences_ascii) { - return wavefront_extend_matches_packed_endsfree(wf_aligner,mwavefront,score,lo,hi); - } else { - wf_offset_t dummy; - return wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,true,&dummy); - } -} -bool wavefront_extend_endsfree_dispatcher_threads( +int wavefront_extend_endsfree( wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, const int score) { - // Parameters + // Modular wavefront + const bool memory_modular = wf_aligner->wf_components.memory_modular; + const int max_score_scope = wf_aligner->wf_components.max_score_scope; + const int score_mod = (memory_modular) ? score % max_score_scope : score; + // Fetch m-wavefront + wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; + if (mwavefront == NULL) { + // Check alignment feasibility (for heuristic variants that can lead to no solution) + if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { + wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; + wf_aligner->align_status.score = score; + return 1; // Done + } + return 0; // Not done + } + // Multithreading dispatcher const int lo = mwavefront->lo; const int hi = mwavefront->hi; bool end_reached = false; const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); if (num_threads == 1) { - // Extend wavefront single-thread - end_reached = wavefront_extend_endsfree_dispatcher_seq(wf_aligner,mwavefront,score,lo,hi); + // Extend wavefront + end_reached = wavefront_extend_matches_packed_endsfree(wf_aligner,mwavefront,score,lo,hi); } else { #ifdef WFA_PARALLEL // Extend wavefront in parallel #pragma omp parallel num_threads(num_threads) { int t_lo, t_hi; - wavefront_compute_thread_limits(omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - if (wavefront_extend_endsfree_dispatcher_seq(wf_aligner,mwavefront,score,t_lo,t_hi)) { + wavefront_compute_thread_limits( + omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + if (wavefront_extend_matches_packed_endsfree(wf_aligner,mwavefront,score,t_lo,t_hi)) { end_reached = true; } } #endif } - // Return end-reached - return end_reached; + if (end_reached) { + wf_aligner->align_status.status = WF_STATUS_END_REACHED; + wf_aligner->align_status.score = score; + return 1; // Done + } + // Cut-off wavefront heuristically + if (wf_aligner->heuristic.strategy != wf_heuristic_none) { + wavefront_heuristic_cufoff(wf_aligner,score,score_mod); + } + return 0; // Not done } -int wavefront_extend_endsfree( +int wavefront_extend_custom( wavefront_aligner_t* const wf_aligner, const int score) { - // Modular wavefront + // Compute score const bool memory_modular = wf_aligner->wf_components.memory_modular; const int max_score_scope = wf_aligner->wf_components.max_score_scope; const int score_mod = (memory_modular) ? score % max_score_scope : score; // Fetch m-wavefront wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; if (mwavefront == NULL) { - // Check alignment feasibility (heuristic variants that can lead to no solution) + // Check alignment feasibility (for heuristic variants that can lead to no solution) if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; wf_aligner->align_status.score = score; @@ -265,8 +476,33 @@ int wavefront_extend_endsfree( } return 0; // Not done } - // Extend (dispatcher) - const bool end_reached = wavefront_extend_endsfree_dispatcher_threads(wf_aligner,mwavefront,score); + // Multithreading dispatcher + const bool endsfree = (wf_aligner->alignment_form.span == alignment_endsfree); + const int lo = mwavefront->lo; + const int hi = mwavefront->hi; + bool end_reached = false; + const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); + if (num_threads == 1) { + // Extend wavefront + end_reached = wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,endsfree); + } else { +#ifdef WFA_PARALLEL + // Extend wavefront in parallel + #pragma omp parallel num_threads(num_threads) + { + int t_lo, t_hi; + wavefront_compute_thread_limits( + omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + if (wavefront_extend_matches_custom(wf_aligner,mwavefront,score,t_lo,t_hi,endsfree)) { + end_reached = true; + } + } +#endif + } + // Check end-to-end finished + if (!endsfree) { + end_reached = wavefront_extend_end2end_check_termination(wf_aligner,mwavefront,score,score_mod); + } if (end_reached) { wf_aligner->align_status.status = WF_STATUS_END_REACHED; wf_aligner->align_status.score = score; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h index 24851d71..93455896 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h @@ -26,7 +26,7 @@ * * PROJECT: Wavefront Alignment Algorithms * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module for the "extension" of exact matches + * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches */ #ifndef WAVEFRONT_EXTEND_H_ @@ -35,18 +35,20 @@ #include "wavefront_aligner.h" /* - * Wavefront extension + * Wavefront exact "extension" */ int wavefront_extend_end2end( wavefront_aligner_t* const wf_aligner, const int score); -int wavefront_extend_endsfree( - wavefront_aligner_t* const wf_aligner, - const int score); - int wavefront_extend_end2end_max( wavefront_aligner_t* const wf_aligner, const int score, int* const max_antidiagonal); +int wavefront_extend_endsfree( + wavefront_aligner_t* const wf_aligner, + const int score); +int wavefront_extend_custom( + wavefront_aligner_t* const wf_aligner, + const int score); #endif /* WAVEFRONT_EXTEND_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c deleted file mode 100644 index fe478693..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module for the "extension" of exact matches - */ - -#include "wavefront_extend_kernels.h" -#include "wavefront_termination.h" - -/* - * Inner-most extend kernel (blockwise comparisons) - */ -FORCE_INLINE wf_offset_t wavefront_extend_matches_packed_kernel( - wavefront_aligner_t* const wf_aligner, - const int k, - wf_offset_t offset) { - // Fetch pattern/text blocks - uint64_t* pattern_blocks = (uint64_t*)(wf_aligner->sequences.pattern+WAVEFRONT_V(k,offset)); - uint64_t* text_blocks = (uint64_t*)(wf_aligner->sequences.text+WAVEFRONT_H(k,offset)); - // Compare 64-bits blocks - uint64_t cmp = *pattern_blocks ^ *text_blocks; - while (__builtin_expect(cmp==0,0)) { - // Increment offset (full block) - offset += 8; - // Next blocks - ++pattern_blocks; - ++text_blocks; - // Compare - cmp = *pattern_blocks ^ *text_blocks; - } - // Count equal characters - const int equal_right_bits = __builtin_ctzl(cmp); - const int equal_chars = DIV_FLOOR(equal_right_bits,8); - offset += equal_chars; - // Return extended offset - return offset; -} -/* - * Wavefront-Extend Inner Kernels - * Wavefront offset extension comparing characters - * Remember: - * - No offset is out of boundaries !(h>tlen,v>plen) - * - if (h==tlen,v==plen) extension won't increment (sentinels) - */ -FORCE_NO_INLINE void wavefront_extend_matches_packed_end2end( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int lo, - const int hi) { - wf_offset_t* const offsets = mwavefront->offsets; - int k; - for (k=lo;k<=hi;++k) { - // Fetch offset - const wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Extend offset - offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); - } -} -FORCE_NO_INLINE wf_offset_t wavefront_extend_matches_packed_end2end_max( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int lo, - const int hi) { - wf_offset_t* const offsets = mwavefront->offsets; - wf_offset_t max_antidiag = 0; - int k; - for (k=lo;k<=hi;++k) { - // Fetch offset - const wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Extend offset - offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); - // Compute max - const wf_offset_t antidiag = WAVEFRONT_ANTIDIAGONAL(k,offsets[k]); - if (max_antidiag < antidiag) max_antidiag = antidiag; - } - return max_antidiag; -} -FORCE_NO_INLINE bool wavefront_extend_matches_packed_endsfree( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi) { - // Parameters - wf_offset_t* const offsets = mwavefront->offsets; - int k; - for (k=lo;k<=hi;++k) { - // Fetch offset - wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Extend offset - offset = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); - offsets[k] = offset; - // Check ends-free reaching boundaries - if (wavefront_termination_endsfree(wf_aligner,mwavefront,score,k,offset)) { - return true; // Quit (we are done) - } - /* - * TODO - const int h_pos = WAVEFRONT_H(k,offset); - const int v_pos = WAVEFRONT_V(k,offset); - if (h_pos >= text_length || v_pos >= pattern_length) { // FIXME Use wherever necessary - if (wavefront_extend_endsfree_check_termination(wf_aligner,mwavefront,score,k,offset)) { - return true; // Quit (we are done) - } - */ - } - // Alignment not finished - return false; -} -/* - * Wavefront-Extend Inner Kernel (Custom match function) - */ -bool wavefront_extend_matches_custom( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi, - const bool endsfree, - wf_offset_t* const max_antidiag) { - // Parameters - wavefront_sequences_t* const seqs = &wf_aligner->sequences; - // Extend diagonally each wavefront point - wf_offset_t* const offsets = mwavefront->offsets; - *max_antidiag = 0; - int k; - for (k=lo;k<=hi;++k) { - // Check offset - wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Count equal characters - int v = WAVEFRONT_V(k,offset); - int h = WAVEFRONT_H(k,offset); - while (wavefront_sequences_cmp(seqs,v,h)) { - h++; v++; offset++; - } - // Update offset - offsets[k] = offset; - // Compute max - const wf_offset_t antidiag = WAVEFRONT_ANTIDIAGONAL(k,offset); - if (*max_antidiag < antidiag) *max_antidiag = antidiag; - // Check ends-free reaching boundaries - if (endsfree && wavefront_termination_endsfree(wf_aligner,mwavefront,score,k,offset)) { - return true; // Quit (we are done) - } - } - // Alignment not finished - return false; -} diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h deleted file mode 100644 index d0a28eb0..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module for the "extension" of exact matches - */ - -#ifndef WAVEFRONT_EXTEND_KERNELS_H_ -#define WAVEFRONT_EXTEND_KERNELS_H_ - -#include "wavefront_aligner.h" - -/* - * Wavefront-Extend Inner Kernels - */ -void wavefront_extend_matches_packed_end2end( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int lo, - const int hi); -wf_offset_t wavefront_extend_matches_packed_end2end_max( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int lo, - const int hi); -bool wavefront_extend_matches_packed_endsfree( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi); - -/* - * Wavefront-Extend Inner Kernel (Custom match function) - */ -bool wavefront_extend_matches_custom( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi, - const bool endsfree, - wf_offset_t* const max_antidiag); - -#endif /* WAVEFRONT_EXTEND_KERNELS_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c deleted file mode 100644 index 0b5278a0..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches - */ - -#include "wavefront_extend.h" -#include "wavefront_align.h" -#include "wavefront_compute.h" -#include "wavefront_heuristic.h" diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h deleted file mode 100644 index 907f5698..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches - */ - -#ifndef WAVEFRONT_EXTEND_H_ -#define WAVEFRONT_EXTEND_H_ - -#include "wavefront_aligner.h" - -#endif /* WAVEFRONT_EXTEND_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c index ae76256a..73ada3e3 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c @@ -259,9 +259,8 @@ void wavefront_heuristic_wfadaptive( wavefront_t* const wavefront, const bool wfmash_mode) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; const int min_wavefront_length = wf_aligner->heuristic.min_wavefront_length; const int max_distance_threshold = wf_aligner->heuristic.max_distance_threshold; wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; @@ -465,9 +464,8 @@ void wavefront_heuristic_banded_adaptive( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; // Check steps if (wf_heuristic->steps_wait > 0) return; @@ -520,6 +518,9 @@ void wavefront_heuristic_cufoff( if (mwavefront == NULL || mwavefront->lo > mwavefront->hi) return; // Decrease wait steps --(wf_heuristic->steps_wait); + // Save lo/hi base + const int hi_base = mwavefront->hi; + const int lo_base = mwavefront->lo; // Select heuristic (WF-Adaptive) if (wf_heuristic->strategy & wf_heuristic_wfadaptive) { wavefront_heuristic_wfadaptive(wf_aligner,mwavefront,false); @@ -539,6 +540,7 @@ void wavefront_heuristic_cufoff( wavefront_heuristic_banded_adaptive(wf_aligner,mwavefront); } // Check wavefront length + if (lo_base == mwavefront->lo && hi_base == mwavefront->hi) return; // No wavefronts pruned if (mwavefront->lo > mwavefront->hi) mwavefront->null = true; // DEBUG // const int wf_length_base = hi_base-lo_base+1; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c index 4f6964ca..1d90db98 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c @@ -152,16 +152,17 @@ int pcigar_unpack_extend_custom( */ void pcigar_unpack_linear( pcigar_t pcigar, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, int* const v_pos, int* const h_pos, char* cigar_buffer, int* const cigar_length) { // Parameters - char* const pattern = sequences->pattern; - const int pattern_length = sequences->pattern_length; - char* const text = sequences->text; - const int text_length = sequences->text_length; char* const cigar_buffer_base = cigar_buffer; // Compute pcigar length and shift to the end of the word int pcigar_length = PCIGAR_MAX_LENGTH; @@ -175,10 +176,10 @@ void pcigar_unpack_linear( for (i=0;imode == wf_sequences_lambda) { // Custom extend-match function + if (match_funct != NULL) { // Custom extend-match function num_matches = pcigar_unpack_extend_custom( - pattern_length,text_length,sequences->match_funct, - sequences->match_funct_arguments,v,h,cigar_buffer); + pattern_length,text_length, + match_funct,match_funct_arguments,v,h,cigar_buffer); } else { num_matches = pcigar_unpack_extend( pattern,pattern_length,text,text_length,v,h,cigar_buffer); @@ -203,17 +204,18 @@ void pcigar_unpack_linear( } void pcigar_unpack_affine( pcigar_t pcigar, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, int* const v_pos, int* const h_pos, char* cigar_buffer, int* const cigar_length, affine_matrix_type* const current_matrix_type) { // Parameters - char* const pattern = sequences->pattern; - const int pattern_length = sequences->pattern_length; - char* const text = sequences->text; - const int text_length = sequences->text_length; char* const cigar_buffer_base = cigar_buffer; // Compute pcigar length and shift to the end of the word int pcigar_length = PCIGAR_MAX_LENGTH; @@ -229,10 +231,10 @@ void pcigar_unpack_affine( // Extend exact-matches if (matrix_type == affine_matrix_M) { // Extend only on the M-wavefront int num_matches; - if (sequences->mode == wf_sequences_lambda) { // Custom extend-match function + if (match_funct != NULL) { // Custom extend-match function num_matches = pcigar_unpack_extend_custom( - pattern_length,text_length,sequences->match_funct, - sequences->match_funct_arguments,v,h,cigar_buffer); + pattern_length,text_length, + match_funct,match_funct_arguments,v,h,cigar_buffer); } else { num_matches = pcigar_unpack_extend( pattern,pattern_length,text,text_length,v,h,cigar_buffer); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h index 0f2edb7e..803fcc26 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h @@ -33,7 +33,6 @@ #define WAVEFRONT_PACKED_CIGAR_H_ #include "wavefront_attributes.h" -#include "wavefront_sequences.h" /* * Configuration @@ -91,14 +90,24 @@ int pcigar_unpack( */ void pcigar_unpack_linear( pcigar_t pcigar, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, int* const v_pos, int* const h_pos, char* cigar_buffer, int* const cigar_length); void pcigar_unpack_affine( pcigar_t pcigar, - wavefront_sequences_t* const sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + alignment_match_funct_t const match_funct, + void* const match_funct_arguments, int* const v_pos, int* const h_pos, char* cigar_buffer, diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c index 28c64c00..a7ca0412 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c @@ -136,11 +136,10 @@ void wavefront_plot_component( // Check wavefront if (wavefront == NULL) return; // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; - const char* const pattern = sequences->pattern; - const char* const text = sequences->text; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; + const char* const pattern = wf_aligner->pattern; + const char* const text = wf_aligner->text; wavefront_plot_t* const plot = wf_aligner->plot; const bool reverse = (wf_aligner->align_mode == wf_align_biwfa_breakpoint_reverse); // Traverse all offsets @@ -255,26 +254,24 @@ void wavefront_plot_print( // Parameters const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; wavefront_plot_t* const wf_plot = wf_aligner->plot; - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; // Metadata - if (sequences->mode == wf_sequences_lambda) { - fprintf(stream,"# PatternLength %d\n",pattern_length); - fprintf(stream,"# TextLength %d\n",text_length); + if (wf_aligner->match_funct != NULL) { + fprintf(stream,"# PatternLength 0\n"); + fprintf(stream,"# TextLength 0\n"); fprintf(stream,"# Pattern -\n"); fprintf(stream,"# Text -\n"); } else { - fprintf(stream,"# PatternLength %d\n",pattern_length); - fprintf(stream,"# Pattern %.*s\n",pattern_length,sequences->pattern); - fprintf(stream,"# TextLength %d\n",text_length); - fprintf(stream,"# Text %.*s\n",text_length,sequences->text); + fprintf(stream,"# PatternLength %d\n",wf_aligner->pattern_length); + fprintf(stream,"# Pattern %.*s\n",wf_aligner->pattern_length,wf_aligner->pattern); + fprintf(stream,"# TextLength %d\n",wf_aligner->text_length); + fprintf(stream,"# Text %.*s\n",wf_aligner->text_length,wf_aligner->text); } fprintf(stream,"# Penalties "); wavefront_penalties_print(stream,&wf_aligner->penalties); fprintf(stream,"\n"); // Alignment mode fprintf(stream,"# WFAMode "); + wavefront_aligner_print_mode(stream,wf_aligner); wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; if (wf_heuristic->strategy != wf_heuristic_none) { wavefront_heuristic_print(stream,wf_heuristic); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c deleted file mode 100644 index 4551537d..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module to encapsulate the input sequences - */ - -#include "wavefront_sequences.h" - -/* - * Configuration - */ -#define WF_SEQUENCES_PADDING 64 -#define WF_SEQUENCES_PATTERN_EOS '!' -#define WF_SEQUENCES_TEXT_EOS '?' - -/* - * Setup - */ -void wavefront_sequences_allocate( - wavefront_sequences_t* const wf_sequences) { - // Mode - wf_sequences->mode = wf_sequences_ascii; - wf_sequences->reverse = false; - // Source sequences - wf_sequences->seq_buffer = NULL; - wf_sequences->seq_buffer_allocated = 0; - // Current state - wf_sequences->pattern = NULL; - wf_sequences->text = NULL; -} -void wavefront_sequences_free( - wavefront_sequences_t* const wf_sequences) { - // Free internal buffers - if (wf_sequences->seq_buffer != NULL) free(wf_sequences->seq_buffer); -} -/* - * Init Sequences - */ -void wavefront_sequences_init_allocate( - wavefront_sequences_t* const wf_sequences, - const int pattern_length, - const int text_length) { - // Compute dimensions - const int buffer_size = pattern_length + text_length + 3*WF_SEQUENCES_PADDING; - // Check internal buffer allocated - if (wf_sequences->seq_buffer_allocated < buffer_size) { - // Free - if (wf_sequences->seq_buffer != NULL) free(wf_sequences->seq_buffer); - // Allocate - const int proposed_size = buffer_size + buffer_size/2; - wf_sequences->seq_buffer = malloc(proposed_size); - wf_sequences->seq_buffer_allocated = proposed_size; - } - // Assign memory - wf_sequences->pattern_buffer = wf_sequences->seq_buffer + WF_SEQUENCES_PADDING; - wf_sequences->text_buffer = wf_sequences->seq_buffer + WF_SEQUENCES_PADDING + pattern_length + WF_SEQUENCES_PADDING; -} -void wavefront_sequences_init_copy( - char* const buffer_dst, - const char* const sequence, - const int sequence_length, - const int padding_length, - const char padding_value, - const bool reverse) { - // Copy sequence - if (reverse) { - int i; - for (i=0;i>2 & 3)]; - const char letter2 = dna_packed2bits_decode[(word>>4 & 3)]; - const char letter3 = dna_packed2bits_decode[(word>>6 & 3)]; - if (reverse) { - buffer_dst[buffer_pos ] = letter0; - buffer_dst[buffer_pos-1] = letter1; - buffer_dst[buffer_pos-2] = letter2; - buffer_dst[buffer_pos-3] = letter3; - buffer_pos -= 4; - } else { - buffer_dst[buffer_pos ] = letter0; - buffer_dst[buffer_pos+1] = letter1; - buffer_dst[buffer_pos+2] = letter2; - buffer_dst[buffer_pos+3] = letter3; - buffer_pos += 4; - } - } - // Add end padding - buffer_dst[sequence_length] = padding_value; -} -void wavefront_sequences_init_ascii( - wavefront_sequences_t* const wf_sequences, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const bool reverse) { - // Mode - wf_sequences->mode = wf_sequences_ascii; - wf_sequences->reverse = reverse; - // Allocate buffers - wavefront_sequences_init_allocate(wf_sequences,pattern_length,text_length); - // Copy internal sequences - wavefront_sequences_init_copy(wf_sequences->pattern_buffer, - pattern,pattern_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_PATTERN_EOS,reverse); - wf_sequences->pattern_buffer_length = pattern_length; - wavefront_sequences_init_copy(wf_sequences->text_buffer, - text,text_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_TEXT_EOS,reverse); - wf_sequences->text_buffer_length = text_length; - // Set pattern - wf_sequences->pattern = wf_sequences->pattern_buffer; - wf_sequences->pattern_begin = 0; - wf_sequences->pattern_length = pattern_length; - wf_sequences->pattern_eos = wf_sequences->pattern[pattern_length]; - // Set text - wf_sequences->text = wf_sequences->text_buffer; - wf_sequences->text_begin = 0; - wf_sequences->text_length = text_length; - wf_sequences->text_eos = wf_sequences->text[text_length]; -} -void wavefront_sequences_init_lambda( - wavefront_sequences_t* const wf_sequences, - alignment_match_funct_t match_funct, - void* match_funct_arguments, - const int pattern_length, - const int text_length, - const bool reverse) { - // Mode - wf_sequences->mode = wf_sequences_lambda; - wf_sequences->reverse = reverse; - // Set sequences' length - wf_sequences->pattern = NULL; - wf_sequences->text = NULL; - wf_sequences->pattern_begin = 0; - wf_sequences->pattern_length = pattern_length; - wf_sequences->text_begin = 0; - wf_sequences->text_length = text_length; - // Internals - wf_sequences->match_funct = match_funct; - wf_sequences->match_funct_arguments = match_funct_arguments; -} -void wavefront_sequences_init_packed2bits( - wavefront_sequences_t* const wf_sequences, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length, - const bool reverse) { - // Mode - wf_sequences->mode = wf_sequences_ascii; - wf_sequences->reverse = reverse; - // Allocate buffers - wavefront_sequences_init_allocate(wf_sequences,pattern_length,text_length); - // Copy internal sequences - wavefront_sequences_init_decode2bits(wf_sequences->pattern_buffer, - pattern,pattern_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_PATTERN_EOS,reverse); - wf_sequences->pattern_buffer_length = pattern_length; - wavefront_sequences_init_decode2bits(wf_sequences->text_buffer, - text,text_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_TEXT_EOS,reverse); - wf_sequences->text_buffer_length = text_length; - // Set pattern - wf_sequences->pattern = wf_sequences->pattern_buffer; - wf_sequences->pattern_begin = 0; - wf_sequences->pattern_length = pattern_length; - wf_sequences->pattern_eos = wf_sequences->pattern[pattern_length]; - // Set text - wf_sequences->text = wf_sequences->text_buffer; - wf_sequences->text_begin = 0; - wf_sequences->text_length = text_length; - wf_sequences->text_eos = wf_sequences->text[text_length]; -} -/* - * Accessors - */ -bool wavefront_sequences_cmp( - wavefront_sequences_t* const wf_sequences, - const int pattern_pos, - const int text_pos) { - // Select mode - if (wf_sequences->mode == wf_sequences_lambda) { - // Custom function to compare sequences - alignment_match_funct_t match_funct = wf_sequences->match_funct; - void* match_funct_arguments = wf_sequences->match_funct_arguments; - // Check coordinates (EOS) - const int pattern_length = wf_sequences->pattern_length; - const int text_length = wf_sequences->text_length; - if (pattern_pos >= pattern_length || text_pos >= text_length) return false; - // Compare using lambda (given coordinates) - const int pattern_begin = wf_sequences->pattern_begin; - const int text_begin = wf_sequences->text_begin; - if (wf_sequences->reverse) { - const int pattern_end = pattern_begin + pattern_length - 1; - const int text_end = text_begin + text_length - 1; - return match_funct(pattern_end-pattern_pos,text_end-text_pos,match_funct_arguments); - } else { - return match_funct(pattern_begin+pattern_pos,text_begin+text_pos,match_funct_arguments); - } - } else { - // Compare regular strings - return wf_sequences->pattern[pattern_pos] == wf_sequences->text[text_pos]; - } -} -char wavefront_sequences_get_pattern( - wavefront_sequences_t* const wf_sequences, - const int position) { - if (wf_sequences->mode == wf_sequences_lambda) { - return '-'; - } else { - return wf_sequences->pattern[position]; - } -} -char wavefront_sequences_get_text( - wavefront_sequences_t* const wf_sequences, - const int position) { - if (wf_sequences->mode == wf_sequences_lambda) { - return '-'; - } else { - return wf_sequences->text[position]; - } -} -/* - * Resize/Update - */ -void wavefront_sequences_set_bounds( - wavefront_sequences_t* const wf_sequences, - const int pattern_begin, - const int pattern_end, - const int text_begin, - const int text_end) { - // Select mode - if (wf_sequences->mode != wf_sequences_lambda) { - // Restore previous EOS char - const int pattern_length_old = wf_sequences->pattern_length; - const int text_length_old = wf_sequences->text_length; - wf_sequences->pattern[pattern_length_old] = wf_sequences->pattern_eos; - wf_sequences->text[text_length_old] = wf_sequences->text_eos; - // Focus on the new section of the sequences - if (wf_sequences->reverse) { - // Compare given coordinates - wf_sequences->pattern = wf_sequences->pattern_buffer + (wf_sequences->pattern_buffer_length - pattern_end); - wf_sequences->text = wf_sequences->text_buffer + (wf_sequences->text_buffer_length - text_end); - } else { - wf_sequences->pattern = wf_sequences->pattern_buffer + pattern_begin; - wf_sequences->text = wf_sequences->text_buffer + text_begin; - } - // Save EOS char and truncate sequence - const int pattern_length_new = pattern_end - pattern_begin; - const int text_length_new = text_end - text_begin; - wf_sequences->pattern_eos = wf_sequences->pattern[pattern_length_new]; - wf_sequences->text_eos = wf_sequences->text[text_length_new]; - wf_sequences->pattern[pattern_length_new] = WF_SEQUENCES_PATTERN_EOS; - wf_sequences->text[text_length_new] = WF_SEQUENCES_TEXT_EOS; - } - // Set bounds - wf_sequences->pattern_begin = pattern_begin; - wf_sequences->pattern_length = pattern_end - pattern_begin; - wf_sequences->text_begin = text_begin; - wf_sequences->text_length = text_end - text_begin; -} - diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h deleted file mode 100644 index 7e047c3c..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module to encapsulate the input sequences - */ - -#ifndef WAVEFRONT_SEQUENCES_H_ -#define WAVEFRONT_SEQUENCES_H_ - -#include "utils/commons.h" - -/* - * Custom extend-match function, e.g.: - * - * typedef struct { - * char* pattern; - * int pattern_length; - * char* text; - * int text_length; - * } match_function_params_t; - * - * int match_function(int v,int h,void* arguments) { - * // Extract parameters - * match_function_params_t* match_arguments = (match_function_params_t*)arguments; - * // Check match - * if (v > match_arguments->pattern_length || h > match_arguments->text_length) return 0; - * return (match_arguments->pattern[v] == match_arguments->text[h]); - * } - */ -typedef int (*alignment_match_funct_t)(int,int,void*); - -/* - * Wavefront Sequences - */ -typedef enum { - wf_sequences_ascii = 0, - wf_sequences_lambda = 1, - wf_sequences_packed2bits = 2, -} wf_sequences_mode_t; -typedef struct { - // Mode - wf_sequences_mode_t mode; // Sequences mode - bool reverse; // Reverse sequences - // Current sequences & bounds - char* pattern; // Pointer to current pattern sequence (padded) - char* text; // Pointer to current text sequence (padded) - int pattern_begin; // Pattern begin offset - int pattern_length; // Pattern length - int text_begin; // Text begin offset - int text_length; // Text length - // Lambda Sequence - alignment_match_funct_t match_funct; // Custom matching function (match(v,h,args)) - void* match_funct_arguments; // Generic arguments passed to matching function (args) - // Internal buffers (ASCII encoded) - char* seq_buffer; // Internal buffer - int seq_buffer_allocated; // Internal buffer allocated - char* pattern_buffer; // Source pattern sequence - char* text_buffer; // Source text sequence - int pattern_buffer_length; // Source pattern length - int text_buffer_length; // Source text length - char pattern_eos; // Source pattern char at EOS - char text_eos; // Source pattern char at EOS -} wavefront_sequences_t; - -/* - * Setup - */ -void wavefront_sequences_allocate( - wavefront_sequences_t* const wf_sequences); -void wavefront_sequences_free( - wavefront_sequences_t* const wf_sequences); - -/* - * Init Sequences - */ -void wavefront_sequences_init_ascii( - wavefront_sequences_t* const wf_sequences, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const bool reverse); -void wavefront_sequences_init_lambda( - wavefront_sequences_t* const wf_sequences, - alignment_match_funct_t match_funct, - void* match_funct_arguments, - const int pattern_length, - const int text_length, - const bool reverse); -void wavefront_sequences_init_packed2bits( - wavefront_sequences_t* const wf_sequences, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length, - const bool reverse); - - -/* - * Accessors - */ -bool wavefront_sequences_cmp( - wavefront_sequences_t* const wf_sequences, - const int pattern_pos, - const int text_pos); -char wavefront_sequences_get_pattern( - wavefront_sequences_t* const wf_sequences, - const int position); -char wavefront_sequences_get_text( - wavefront_sequences_t* const wf_sequences, - const int position); - -/* - * Resize/Update - */ -void wavefront_sequences_set_bounds( - wavefront_sequences_t* const wf_sequences, - const int pattern_begin, - const int pattern_end, - const int text_begin, - const int text_end); - -#endif /* WAVEFRONT_SEQUENCES_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c deleted file mode 100644 index e9e91bb8..00000000 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WFA module to check for the termination of an alignment - */ - -#include "wavefront_termination.h" - -/* - * Detect alignment termination (end of alignment) - */ -FORCE_NO_INLINE bool wavefront_termination_end2end( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int score_mod) { - // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; - const affine2p_matrix_type component_end = wf_aligner->component_end; - const int alignment_k = DPMATRIX_DIAGONAL(text_length,pattern_length); - const wf_offset_t alignment_offset = DPMATRIX_OFFSET(text_length,pattern_length); - // Select end component - switch (component_end) { - case affine2p_matrix_M: { - // Check diagonal/offset - if (mwavefront->lo > alignment_k || alignment_k > mwavefront->hi) return false; // Not done - const wf_offset_t moffset = mwavefront->offsets[alignment_k]; - if (moffset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_I1: { - // Fetch I1-wavefront & check diagonal/offset - wavefront_t* const i1wavefront = wf_aligner->wf_components.i1wavefronts[score_mod]; - if (i1wavefront == NULL || i1wavefront->lo > alignment_k || alignment_k > i1wavefront->hi) return false; // Not done - const wf_offset_t i1offset = i1wavefront->offsets[alignment_k]; - if (i1offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_I2: { - // Fetch I2-wavefront & check diagonal/offset - wavefront_t* const i2wavefront = wf_aligner->wf_components.i2wavefronts[score_mod]; - if (i2wavefront == NULL || i2wavefront->lo > alignment_k || alignment_k > i2wavefront->hi) return false; // Not done - const wf_offset_t i2offset = i2wavefront->offsets[alignment_k]; - if (i2offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_D1: { - // Fetch D1-wavefront & check diagonal/offset - wavefront_t* const d1wavefront = wf_aligner->wf_components.d1wavefronts[score_mod]; - if (d1wavefront == NULL || d1wavefront->lo > alignment_k || alignment_k > d1wavefront->hi) return false; // Not done - const wf_offset_t d1offset = d1wavefront->offsets[alignment_k]; - if (d1offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_D2: { - // Fetch D2-wavefront & check diagonal/offset - wavefront_t* const d2wavefront = wf_aligner->wf_components.d2wavefronts[score_mod]; - if (d2wavefront == NULL || d2wavefront->lo > alignment_k || alignment_k > d2wavefront->hi) return false; // Not done - const wf_offset_t d2offset = d2wavefront->offsets[alignment_k]; - if (d2offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - default: - break; - } - return false; -} -FORCE_NO_INLINE bool wavefront_termination_endsfree( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int k, - const wf_offset_t offset) { - // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; - // Check ends-free reaching boundaries - const int h_pos = WAVEFRONT_H(k,offset); - const int v_pos = WAVEFRONT_V(k,offset); - if (h_pos >= text_length) { // Text is aligned - // Is Pattern end-free? - const int pattern_left = pattern_length - v_pos; - const int pattern_end_free = wf_aligner->alignment_form.pattern_end_free; - if (pattern_left <= pattern_end_free) { - #ifdef WFA_PARALLEL - #pragma omp critical - #endif - { - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = k; - wf_aligner->alignment_end_pos.offset = offset; - } - return true; // Quit (we are done) - } - } - if (v_pos >= pattern_length) { // Pattern is aligned - // Is text end-free? - const int text_left = text_length - h_pos; - const int text_end_free = wf_aligner->alignment_form.text_end_free; - if (text_left <= text_end_free) { - #ifdef WFA_PARALLEL - #pragma omp critical - #endif - { - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = k; - wf_aligner->alignment_end_pos.offset = offset; - } - return true; // Quit (we are done) - } - } - // Not done - return false; -} diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c index 3ccaf3af..4e733ae9 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c @@ -48,6 +48,11 @@ #include "wavefront_backtrace.h" #include "wavefront_backtrace_buffer.h" +/* + * Configuration + */ +#define SEQUENCES_PADDING 10 + /* * Setup */ @@ -71,17 +76,35 @@ void wavefront_unialigner_system_clear( default: break; } + // Profile + timer_reset(&wf_aligner->system.timer); } /* * Resize */ void wavefront_unialign_resize( - wavefront_aligner_t* const wf_aligner) { - // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; - // Configure status + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const bool reverse_sequences) { + // Configure sequences and status + wf_aligner->pattern_length = pattern_length; + wf_aligner->text_length = text_length; + if (wf_aligner->match_funct == NULL) { + if (wf_aligner->sequences != NULL) strings_padded_delete(wf_aligner->sequences); + wf_aligner->sequences = strings_padded_new_rhomb( + pattern,pattern_length,text,text_length, + SEQUENCES_PADDING,reverse_sequences, + wf_aligner->mm_allocator); + wf_aligner->pattern = wf_aligner->sequences->pattern_padded; + wf_aligner->text = wf_aligner->sequences->text_padded; + } else { + wf_aligner->sequences = NULL; + wf_aligner->pattern = NULL; + wf_aligner->text = NULL; + } wavefront_unialign_status_clear(&wf_aligner->align_status); // Heuristics clear wavefront_heuristic_clear(&wf_aligner->heuristic); @@ -100,14 +123,155 @@ void wavefront_unialign_resize( /* * Initialize alignment */ +void wavefront_unialign_initialize_wavefront_m( + wavefront_aligner_t* const wf_aligner, + const int pattern_length, + const int text_length) { + // Parameters + wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; + wavefront_components_t* const wf_components = &wf_aligner->wf_components; + const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; + wavefront_penalties_t* const penalties = &wf_aligner->penalties; + alignment_form_t* const form = &wf_aligner->alignment_form; + // Consider ends-free + const int hi = (penalties->match==0) ? form->text_begin_free : 0; + const int lo = (penalties->match==0) ? -form->pattern_begin_free : 0; + // Compute dimensions + int effective_lo, effective_hi; + wavefront_compute_limits_output(wf_aligner,lo,hi,&effective_lo,&effective_hi); + // Initialize end2end (wavefront zero) + wf_components->mwavefronts[0] = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); + wf_components->mwavefronts[0]->offsets[0] = 0; + wf_components->mwavefronts[0]->lo = lo; + wf_components->mwavefronts[0]->hi = hi; + // Store initial BT-piggypack element + if (wf_components->bt_piggyback) { + const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,0); + wf_components->mwavefronts[0]->bt_pcigar[0] = 0; + wf_components->mwavefronts[0]->bt_prev[0] = block_idx; + } + // Initialize ends-free + if (form->span == alignment_endsfree && penalties->match == 0) { + // Text begin-free + const int text_begin_free = form->text_begin_free; + int h; + for (h=1;h<=text_begin_free;++h) { + const int k = DPMATRIX_DIAGONAL(h,0); + wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(h,0); + if (wf_components->bt_piggyback) { + const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,h); + wf_components->mwavefronts[0]->bt_pcigar[k] = 0; + wf_components->mwavefronts[0]->bt_prev[k] = block_idx; + } + } + // Pattern begin-free + const int pattern_begin_free = form->pattern_begin_free; + int v; + for (v=1;v<=pattern_begin_free;++v) { + const int k = DPMATRIX_DIAGONAL(0,v); + wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(0,v); + if (wf_components->bt_piggyback) { + const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,v,0); + wf_components->mwavefronts[0]->bt_pcigar[k] = 0; + wf_components->mwavefronts[0]->bt_prev[k] = block_idx; + } + } + } + // Nullify unused WFs + if (distance_metric <= gap_linear) return; + wf_components->d1wavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + if (distance_metric==gap_affine) return; + wf_components->d2wavefronts[0] = NULL; + wf_components->i2wavefronts[0] = NULL; +} +void wavefront_unialign_initialize_wavefronts( + wavefront_aligner_t* const wf_aligner, + const int pattern_length, + const int text_length) { + // Parameters + wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; + wavefront_components_t* const wf_components = &wf_aligner->wf_components; + const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; + // Init wavefronts + if (wf_aligner->component_begin == affine2p_matrix_M) { + // Initialize + wavefront_unialign_initialize_wavefront_m(wf_aligner,pattern_length,text_length); + // Nullify unused WFs + if (distance_metric <= gap_linear) return; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = NULL; + if (distance_metric==gap_affine) return; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = NULL; + } else { + // Compute dimensions + int effective_lo, effective_hi; // Effective lo/hi + wavefront_compute_limits_output(wf_aligner,0,0,&effective_lo,&effective_hi); + wavefront_t* const wavefront = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); + // Initialize + switch (wf_aligner->component_begin) { + case affine2p_matrix_I1: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = wavefront; + wf_components->i1wavefronts[0]->offsets[0] = 0; + wf_components->i1wavefronts[0]->lo = 0; + wf_components->i1wavefronts[0]->hi = 0; + wf_components->d1wavefronts[0] = NULL; + // Nullify unused WFs + if (distance_metric==gap_affine) return; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = NULL; + break; + case affine2p_matrix_I2: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = NULL; + wf_components->i2wavefronts[0] = wavefront; + wf_components->i2wavefronts[0]->offsets[0] = 0; + wf_components->i2wavefronts[0]->lo = 0; + wf_components->i2wavefronts[0]->hi = 0; + wf_components->d2wavefronts[0] = NULL; + break; + case affine2p_matrix_D1: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = wavefront; + wf_components->d1wavefronts[0]->offsets[0] = 0; + wf_components->d1wavefronts[0]->lo = 0; + wf_components->d1wavefronts[0]->hi = 0; + // Nullify unused WFs + if (distance_metric==gap_affine) return; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = NULL; + break; + case affine2p_matrix_D2: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = NULL; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = wavefront; + wf_components->d2wavefronts[0]->offsets[0] = 0; + wf_components->d2wavefronts[0]->lo = 0; + wf_components->d2wavefronts[0]->hi = 0; + break; + default: + break; + } + } +} void wavefront_unialign_init( wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end) { // Parameters wavefront_align_status_t* const align_status = &wf_aligner->align_status; // Resize wavefront aligner - wavefront_unialign_resize(wf_aligner); + wavefront_unialign_resize(wf_aligner,pattern,pattern_length,text,text_length,false); // Configure WF-compute function switch (wf_aligner->penalties.distance_metric) { case indel: @@ -130,18 +294,19 @@ void wavefront_unialign_init( } // Configure WF-extend function const bool end2end = (wf_aligner->alignment_form.span == alignment_end2end); - if (end2end) { + if (wf_aligner->match_funct != NULL) { + align_status->wf_align_extend = &wavefront_extend_custom; + } else if (end2end) { align_status->wf_align_extend = &wavefront_extend_end2end; } else { align_status->wf_align_extend = &wavefront_extend_endsfree; } // Initialize wavefront - align_status->num_null_steps = 0; wf_aligner->alignment_end_pos.score = -1; // Not aligned wf_aligner->alignment_end_pos.k = DPMATRIX_DIAGONAL_NULL; wf_aligner->component_begin = component_begin; wf_aligner->component_end = component_end; - wavefront_aligner_init_wf(wf_aligner); + wavefront_unialign_initialize_wavefronts(wf_aligner,pattern_length,text_length); // Plot (WF_0) if (wf_aligner->plot != NULL) wavefront_plot(wf_aligner,0,0); } @@ -153,7 +318,7 @@ bool wavefront_unialign_reached_limits( const int score) { // Check alignment-score limit if (score >= wf_aligner->system.max_alignment_score) { - wf_aligner->cigar->score = -wf_aligner->system.max_alignment_score; + wf_aligner->cigar->score = wf_aligner->system.max_alignment_score; wf_aligner->align_status.status = WF_STATUS_MAX_SCORE_REACHED; wf_aligner->align_status.score = score; return true; // Stop @@ -201,9 +366,8 @@ void wavefront_unialign_terminate( wavefront_aligner_t* const wf_aligner, const int score) { // Parameters - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; + const int pattern_length = wf_aligner->pattern_length; + const int text_length = wf_aligner->text_length; // Retrieve alignment if (wf_aligner->alignment_scope == compute_score) { cigar_clear(wf_aligner->cigar); @@ -253,6 +417,7 @@ int wavefront_unialign( void (*wf_align_compute)(wavefront_aligner_t* const,const int) = align_status->wf_align_compute; int (*wf_align_extend)(wavefront_aligner_t* const,const int) = align_status->wf_align_extend; // Compute wavefronts of increasing score + align_status->num_null_steps = 0; int score = align_status->score; while (true) { // Exact extend s-wavefront @@ -289,11 +454,8 @@ void wavefront_unialign_print_status( const int score) { // Parameters wavefront_components_t* const wf_components = &wf_aligner->wf_components; - wavefront_sequences_t* const sequences = &wf_aligner->sequences; - const int pattern_length = sequences->pattern_length; - const int text_length = sequences->text_length; // Approximate progress - const int dist_total = MAX(text_length,pattern_length); + const int dist_total = MAX(wf_aligner->text_length,wf_aligner->pattern_length); int s = (wf_components->memory_modular) ? score%wf_components->max_score_scope : score; wavefront_t* wavefront = wf_components->mwavefronts[s]; if (wavefront==NULL && s>0) { @@ -318,16 +480,11 @@ void wavefront_unialign_print_status( const float million_offsets = (wf_len>=0) ? (float)wf_len/1000000.0f : -1.0f; // Print one-line status fprintf(stream,"["); - wavefront_aligner_print_mode(stream,wf_aligner); + wavefront_aligner_print_type(stream,wf_aligner); fprintf(stream, "] SequenceLength=(%d,%d) Score %d (~ %2.3f%% aligned). " "MemoryUsed(WF-Slab,BT-buffer)=(%lu MB,%lu MB). " "Wavefronts ~ %2.3f Moffsets\n", - pattern_length, - text_length, - score, - aligned_progress, - CONVERT_B_TO_MB(slab_size), - CONVERT_B_TO_MB(bt_buffer_used), - million_offsets); + wf_aligner->pattern_length,wf_aligner->text_length,score,aligned_progress, + CONVERT_B_TO_MB(slab_size),CONVERT_B_TO_MB(bt_buffer_used),million_offsets); } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h index b039ee5c..4c29dbd6 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h @@ -37,13 +37,26 @@ * Resize */ void wavefront_unialign_resize( - wavefront_aligner_t* const wf_aligner); + wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const bool reverse_sequences); /* * Initialize alignment */ +void wavefront_unialign_initialize_wavefronts( + wavefront_aligner_t* const wf_aligner, + const int pattern_length, + const int text_length); void wavefront_unialign_init( wavefront_aligner_t* const wf_aligner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h b/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h index e29c0eb1..1514758a 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h @@ -32,13 +32,14 @@ #pragma once #include "system/mm_allocator.h" -#include "wavefront_slab.h" -#include "wavefront_penalties.h" +#include "utils/string_padded.h" #include "wavefront_attributes.h" #include "wavefront_components.h" -#include "wavefront_sequences.h" +#include "wavefront_slab.h" +#include "wavefront_penalties.h" #include "wavefront_bialigner.h" + /* * Error codes & messages */ @@ -53,7 +54,6 @@ // Error messages extern char* wf_error_msg[5]; char* wavefront_align_strerror(const int error_code); -char* wavefront_align_strerror_short(const int error_code); /* * Alignment status @@ -90,7 +90,14 @@ typedef struct _wavefront_aligner_t { char* align_mode_tag; // WFA mode tag wavefront_align_status_t align_status; // Current alignment status // Sequences - wavefront_sequences_t sequences; // Input sequences + strings_padded_t* sequences; // Padded sequences + char* pattern; // Pattern sequence (padded) + int pattern_length; // Pattern length + char* text; // Text sequence (padded) + int text_length; // Text length + // Custom function to compare sequences + alignment_match_funct_t match_funct; // Custom matching function (match(v,h,args)) + void* match_funct_arguments; // Generic arguments passed to matching function (args) // Alignment Attributes alignment_scope_t alignment_scope; // Alignment scope (score only or full-CIGAR) alignment_form_t alignment_form; // Alignment form (end-to-end/ends-free) @@ -126,12 +133,6 @@ void wavefront_aligner_reap( void wavefront_aligner_delete( wavefront_aligner_t* const wf_aligner); -/* - * Initialize wf-alignment conditions - */ -void wavefront_aligner_init_wf( - wavefront_aligner_t* const wf_aligner); - /* * Span configuration */ @@ -177,6 +178,14 @@ void wavefront_aligner_set_heuristic_banded_adaptive( const int band_max_k, const int score_steps); +/* + * Match-funct configuration + */ +void wavefront_aligner_set_match_funct( + wavefront_aligner_t* const wf_aligner, + int (*match_funct)(int,int,void*), + void* const match_funct_arguments); + /* * System configuration */ @@ -202,34 +211,25 @@ uint64_t wavefront_aligner_get_size( /* * Display */ -void wavefront_aligner_print_mode( +void wavefront_aligner_print_type( FILE* const stream, wavefront_aligner_t* const wf_aligner); void wavefront_aligner_print_scope( FILE* const stream, wavefront_aligner_t* const wf_aligner); -void wavefront_aligner_print_conf( +void wavefront_aligner_print_mode( FILE* const stream, wavefront_aligner_t* const wf_aligner); /* - * Wavefront Align + * Wavefront Alignment */ + int wavefront_align( wavefront_aligner_t* const wf_aligner, const char* const pattern, const int pattern_length, const char* const text, const int text_length); -int wavefront_align_lambda( - wavefront_aligner_t* const wf_aligner, - alignment_match_funct_t const match_funct, - void* match_funct_arguments, - const int pattern_length, - const int text_length); -int wavefront_align_packed2bits( - wavefront_aligner_t* const wf_aligner, - const uint8_t* const pattern, - const int pattern_length, - const uint8_t* const text, - const int text_length); +int wavefront_align_resume( + wavefront_aligner_t* const wf_aligner); diff --git a/src/common/wflign/src/wflign.cpp b/src/common/wflign/src/wflign.cpp index 0ad10868..9ba75f6d 100644 --- a/src/common/wflign/src/wflign.cpp +++ b/src/common/wflign/src/wflign.cpp @@ -606,9 +606,8 @@ void WFlign::wflign_affine_wavefront( #endif // Align - wflambda_aligner->alignEnd2EndLambda( - wflambda_extend_match,(void*)&extend_data, - pattern_length,text_length); + wflambda_aligner->setMatchFunct(wflambda_extend_match, (void*)&extend_data); + wflambda_aligner->alignEnd2EndLambda(pattern_length,text_length); // Extract the trace if (wflambda_aligner->getAlignmentStatus() == WF_STATUS_SUCCESSFUL) { diff --git a/src/common/wflign/src/wflign_alignment.cpp b/src/common/wflign/src/wflign_alignment.cpp index 70babf6a..d5f4efa6 100644 --- a/src/common/wflign/src/wflign_alignment.cpp +++ b/src/common/wflign/src/wflign_alignment.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include /* From 072f5100d84ef8c95fccdfe9f3d412cf457d880f Mon Sep 17 00:00:00 2001 From: AndreaGuarracino Date: Thu, 15 Jun 2023 14:48:29 +0200 Subject: [PATCH 2/4] fix --- .../wflign/deps/WFA2-lib/CMakeLists.txt | 5 +- src/common/wflign/deps/WFA2-lib/Makefile | 4 +- src/common/wflign/deps/WFA2-lib/README.md | 40 +- src/common/wflign/deps/WFA2-lib/VERSION.txt | 2 +- .../wflign/deps/WFA2-lib/alignment/cigar.c | 617 ++++++++++++++---- .../wflign/deps/WFA2-lib/alignment/cigar.h | 98 ++- .../deps/WFA2-lib/alignment/score_matrix.c | 1 - .../deps/WFA2-lib/bindings/cpp/WFAligner.cpp | 216 ++++-- .../deps/WFA2-lib/bindings/cpp/WFAligner.hpp | 112 +++- .../wflign/deps/WFA2-lib/examples/Makefile | 3 + .../wflign/deps/WFA2-lib/examples/wfa_basic.c | 5 +- .../deps/WFA2-lib/examples/wfa_bindings.cpp | 2 +- .../deps/WFA2-lib/examples/wfa_lambda.cpp | 5 +- .../wflign/deps/WFA2-lib/img/wfa.endsfree.png | Bin 0 -> 68149 bytes .../WFA2-lib/scripts/wfa.alg.cmp.score.sh | 2 +- .../deps/WFA2-lib/system/mm_allocator.c | 3 + .../wflign/deps/WFA2-lib/system/mm_stack.c | 2 + .../deps/WFA2-lib/system/profiler_counter.h | 3 + .../deps/WFA2-lib/system/profiler_timer.c | 2 +- .../deps/WFA2-lib/system/profiler_timer.h | 1 + .../tests/wfa.utest.check/wfa.utest.log.mem | 120 ++-- .../tests/wfa.utest.check/wfa.utest.log.time | 32 +- .../deps/WFA2-lib/tests/wfa.utest.cmp.sh | 31 +- .../tests/wfa.utest.performance.cmp.sh | 46 -- .../WFA2-lib/tests/wfa.utest.performance.sh | 2 +- .../wflign/deps/WFA2-lib/tests/wfa.utest.sh | 128 ++-- .../tools/align_benchmark/align_benchmark.c | 49 +- .../align_benchmark/align_benchmark_params.c | 36 +- .../align_benchmark/align_benchmark_params.h | 16 +- .../benchmark/benchmark_check.c | 15 +- .../benchmark/benchmark_edit.c | 18 +- .../benchmark/benchmark_gap_affine.c | 21 +- .../benchmark/benchmark_gap_affine2p.c | 15 +- .../benchmark/benchmark_gap_linear.c | 15 +- .../benchmark/benchmark_indel.c | 12 +- .../benchmark/benchmark_utils.c | 38 +- .../benchmark/benchmark_utils.h | 2 + .../tools/align_benchmark/edit/edit_bpm.c | 2 +- .../wflign/deps/WFA2-lib/utils/Makefile | 1 - .../wflign/deps/WFA2-lib/utils/commons.h | 1 - .../wflign/deps/WFA2-lib/utils/heatmap.h | 2 + .../deps/WFA2-lib/utils/string_padded.c | 140 ---- .../wflign/deps/WFA2-lib/wavefront/Makefile | 4 + .../deps/WFA2-lib/wavefront/wavefront_align.c | 151 +++-- .../deps/WFA2-lib/wavefront/wavefront_align.h | 14 +- .../WFA2-lib/wavefront/wavefront_aligner.c | 418 +++++++++--- .../WFA2-lib/wavefront/wavefront_aligner.h | 31 + .../WFA2-lib/wavefront/wavefront_attributes.c | 6 +- .../WFA2-lib/wavefront/wavefront_attributes.h | 28 +- .../WFA2-lib/wavefront/wavefront_backtrace.c | 30 +- .../wavefront/wavefront_backtrace_buffer.c | 39 +- .../wavefront/wavefront_backtrace_buffer.h | 14 +- .../wavefront/wavefront_backtrace_offload.c | 1 - .../WFA2-lib/wavefront/wavefront_bialign.c | 549 ++++++++-------- .../WFA2-lib/wavefront/wavefront_bialign.h | 6 +- .../WFA2-lib/wavefront/wavefront_bialigner.c | 169 +++-- .../WFA2-lib/wavefront/wavefront_bialigner.h | 50 +- .../WFA2-lib/wavefront/wavefront_compute.c | 11 +- .../wavefront/wavefront_compute_affine.c | 13 +- .../wavefront/wavefront_compute_affine2p.c | 12 +- .../wavefront/wavefront_compute_edit.c | 26 +- .../wavefront/wavefront_compute_linear.c | 13 +- .../deps/WFA2-lib/wavefront/wavefront_debug.c | 204 +++--- .../deps/WFA2-lib/wavefront/wavefront_debug.h | 10 +- .../WFA2-lib/wavefront/wavefront_extend.c | 507 ++++---------- .../WFA2-lib/wavefront/wavefront_extend.h | 8 +- .../wavefront/wavefront_extend_kernels.c | 177 +++++ .../wavefront_extend_kernels.h} | 68 +- .../wavefront/wavefront_extend_kernels_avx.c | 167 +++++ .../wavefront/wavefront_extend_kernels_avx.h | 47 ++ .../WFA2-lib/wavefront/wavefront_heuristic.c | 60 +- .../WFA2-lib/wavefront/wavefront_heuristic.h | 5 +- .../WFA2-lib/wavefront/wavefront_pcigar.c | 34 +- .../WFA2-lib/wavefront/wavefront_pcigar.h | 15 +- .../WFA2-lib/wavefront/wavefront_penalties.c | 46 +- .../WFA2-lib/wavefront/wavefront_penalties.h | 11 +- .../deps/WFA2-lib/wavefront/wavefront_plot.c | 62 +- .../deps/WFA2-lib/wavefront/wavefront_plot.h | 3 - .../WFA2-lib/wavefront/wavefront_sequences.c | 310 +++++++++ .../WFA2-lib/wavefront/wavefront_sequences.h | 148 +++++ .../wavefront/wavefront_termination.c | 162 +++++ .../wavefront/wavefront_termination.h | 57 ++ .../WFA2-lib/wavefront/wavefront_unialign.c | 368 +++-------- .../WFA2-lib/wavefront/wavefront_unialign.h | 19 - .../wflign/deps/WFA2-lib/wavefront/wfa.h | 95 ++- src/common/wflign/src/wflign.cpp | 10 +- src/common/wflign/src/wflign_alignment.cpp | 2 +- src/common/wflign/src/wflign_patch.cpp | 10 +- 88 files changed, 3743 insertions(+), 2312 deletions(-) create mode 100644 src/common/wflign/deps/WFA2-lib/img/wfa.endsfree.png delete mode 100755 src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh delete mode 100644 src/common/wflign/deps/WFA2-lib/utils/string_padded.c create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c rename src/common/wflign/deps/WFA2-lib/{utils/string_padded.h => wavefront/wavefront_extend_kernels.h} (57%) create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c create mode 100644 src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h diff --git a/src/common/wflign/deps/WFA2-lib/CMakeLists.txt b/src/common/wflign/deps/WFA2-lib/CMakeLists.txt index 07d68747..acb3d906 100644 --- a/src/common/wflign/deps/WFA2-lib/CMakeLists.txt +++ b/src/common/wflign/deps/WFA2-lib/CMakeLists.txt @@ -120,8 +120,12 @@ set(wfa2lib_SOURCE wavefront/wavefront_pcigar.c wavefront/wavefront_penalties.c wavefront/wavefront_plot.c + wavefront/wavefront_sequences.c wavefront/wavefront_slab.c wavefront/wavefront_unialign.c + wavefront/wavefront_termination.c + wavefront/wavefront_extend_kernels_avx.c + wavefront/wavefront_extend_kernels.c system/mm_stack.c system/mm_allocator.c system/profiler_counter.c @@ -132,7 +136,6 @@ set(wfa2lib_SOURCE utils/vector.c utils/commons.c utils/heatmap.c - utils/string_padded.c alignment/affine2p_penalties.c alignment/affine_penalties.c alignment/cigar.c diff --git a/src/common/wflign/deps/WFA2-lib/Makefile b/src/common/wflign/deps/WFA2-lib/Makefile index a77b59ae..69bb5762 100644 --- a/src/common/wflign/deps/WFA2-lib/Makefile +++ b/src/common/wflign/deps/WFA2-lib/Makefile @@ -18,10 +18,10 @@ AR=ar AR_FLAGS=-rsc ifndef BUILD_EXAMPLES -BUILD_EXAMPLES=0 +BUILD_EXAMPLES=1 endif ifndef BUILD_TOOLS -BUILD_TOOLS=0 +BUILD_TOOLS=1 endif ifndef BUILD_WFA_PARALLEL BUILD_WFA_PARALLEL=0 diff --git a/src/common/wflign/deps/WFA2-lib/README.md b/src/common/wflign/deps/WFA2-lib/README.md index 6d05f53f..b5415d22 100644 --- a/src/common/wflign/deps/WFA2-lib/README.md +++ b/src/common/wflign/deps/WFA2-lib/README.md @@ -16,7 +16,7 @@ The WFA2 library implements the WFA algorithm for different distance metrics and ### 1.3 Getting started -Git clone and compile the library, tools, and examples. By default use cmake: +Git clone and compile the library, tools, and examples (by default, use cmake). ``` git clone https://github.com/smarco/WFA2-lib @@ -27,25 +27,28 @@ cmake --build . --verbose ctest . --verbose ``` -There are some flags that can be used: +There are some flags that can be used. For instance: ``` cmake .. -DOPENMP=TRUE +cmake .. -DCMAKE_BUILD_TYPE=Release -DEXTRA_FLAGS="-ftree-vectorizer-verbose=5" ``` -To add vector optimization try +To build a shared library (static is the default). ``` -cmake .. -DCMAKE_BUILD_TYPE=Release -DEXTRA_FLAGS="-ftree-vectorize -msse2 -mfpmath=sse -ftree-vectorizer-verbose=5" +cmake -DBUILD_SHARED_LIBS=ON ``` -To build a shared library (static is the default) +Alternatively, the Makefile build system can be used. ``` -cmake -DBUILD_SHARED_LIBS=ON +$> git clone https://github.com/smarco/WFA2-lib +$> cd WFA2-lib +$> make clean all ``` -It is possible to build WFA2-lib in a GNU Guix container, for more information see [guix.scm](./guix.scm). +Also, it is possible to build WFA2-lib in a GNU Guix container, for more information see [guix.scm](./guix.scm). ### 1.4 Contents (where to go from here) @@ -158,7 +161,7 @@ Display the result of the alignment. ```C++ // Display CIGAR & score -string cigar = aligner.getAlignmentCigar(); +string cigar = aligner.getCIGAR(); cout << "CIGAR: " << cigar << endl; cout << "Alignment score " << aligner.getAlignmentScore() << endl; ``` @@ -417,7 +420,7 @@ The WFA2 library implements various memory modes: `wavefront_memory_high`, `wave ```C wavefront_aligner_attr_t attributes = wavefront_aligner_attr_default; - attributes.memory_mode = wavefront_memory_med; + attributes.memory_mode = wavefront_memory_ultralow; ``` ### 3.5 Heuristic modes @@ -480,7 +483,7 @@ WFA2's heuristics are classified into the following categories: ['wf-adaptive']( attributes.heuristic.steps_between_cutoffs = 100; ``` -        **Z-drop** implements the Z-drop heuristic (as described in Minimap2). This heuristic halts the alignment process if the score drops too fast in the diagonal direction. Let $sw_{max}$ be the maximum observed score so far, computed at cell ($i'$,$j'$). Then, let $sw$ be the maximum score found in the last computed wavefront, computed at cell ($i$,$j$). The Z-drop heuristic stops the alignment process if $sw_{max} - sw > zdrop + gap_e·|(i-i')-(j-j')|$, being $gap_e$ the gap-extension penalty and $zdrop$ a parameter of the heuristic. +        **Z-drop** implements the Z-drop heuristic (as described in Minimap2). This heuristic halts the alignment process if the score drops too fast in the diagonal direction. Let $sw_{max}$ be the maximum observed score so far, computed at cell $(i',j')$. Then, let $sw$ be the maximum score found in the last computed wavefront, computed at cell $(i,j)$. The Z-drop heuristic stops the alignment process if $sw_{max} - sw > zdrop + gap_e·|(i-i')-(j-j')|$, being $gap_e$ the gap-extension penalty and $zdrop$ a parameter of the heuristic. ```C @@ -497,7 +500,7 @@ WFA2's heuristics are classified into the following categories: ['wf-adaptive'](

None

X-drop(200,1)

-

Y-drop(200,1)

+

Z-drop(200,1)

@@ -555,11 +558,16 @@ WFA2's heuristics are classified into the following categories: ['wf-adaptive']( ### 3.6 Some technical notes -- Thanks to Eizenga's formulation, WFA2-lib can operate with any match score. Although, in practice, M=0 is still the most efficient choice. +- Thanks to Eizenga's formulation, WFA2-lib can operate with any match score. In practice, M=0 is often the most efficient choice. + + +- Note that edit and LCS are distance metrics and, thus, the score computed is always positive. However, using weighted distances (e.g., gap-linear and gap-affine) the alignment score is computed using the selected penalties (i.e., the alignment score can be positive or negative). For instance, if WFA2-lib is executed using $M=0$, the final score is expected to be negative. + + +- All WFA2-lib algorithms/variants are stable. That is, for alignments having the same score, the all alignment modes always resolve ties (between M, X, I,and D) using the same criteria: M (highest prio) > X > D > I (lowest prio). Only the memory mode `ultralow` (BiWFA) resolves ties differently (although the results are still optimal). -- Note that edit and LCS are distance metrics and, thus, the score computed is always positive. However, weighted distances, like gap-linear and gap-affine, have the sign of the computed alignment evaluated under the selected penalties. If WFA2-lib is executed using $M=0$, the final score is expected to be negative. -- All WFA2-lib algorithms/variants are stable. That is, for alignments having the same score, the library always resolves ties (between M, X, I,and D) using the same criteria: M (highest prio) > X > D > I (lowest prio). Nevertheless, the memory mode `ultralow` (BiWFA) is optimal (always reports the best alignment) but not stable. +- WFA2lib follows the convention that describes how to transform the (1) Pattern/Query into the (2) Text/Database/Reference used in classic pattern matching papers. However, the SAM CIGAR specification describes the transformation from (2) Reference to (1) Query. If you want CIGAR-compliant alignments, swap the pattern and text sequences argument when calling the WFA2lib's align functions (to convert all the Ds into Is and vice-versa). ## 4. REPORTING BUGS AND FEATURE REQUEST @@ -592,6 +600,6 @@ Miquel Moretó has contributed with fruitful technical discussions and tireless ## 8. CITATION -**Santiago Marco-Sola, Juan Carlos Moure, Miquel Moreto, Antonio Espinosa**. ["Fast gap-affine pairwise alignment using the wavefront algorithm."](https://doi.org/10.1093/bioinformatics/btaa777) Bioinformatics, 2020. +**Santiago Marco-Sola, Juan Carlos Moure, Miquel Moreto, Antonio Espinosa**. ["Fast gap-affine pairwise alignment using the wavefront algorithm."](https://doi.org/10.1093/bioinformatics/btaa777). Bioinformatics, 2020. -**Santiago Marco-Sola, Jordan M Eizenga, Andrea Guarracino, Benedict Paten, Erik Garrison, Miquel Moreto**. Optimal gap-affine alignment in O(s) space. _bioRxiv_ (2022). DOI [2022.04.14.488380](https://doi.org/10.1101/2022.04.14.488380) +**Santiago Marco-Sola, Jordan M Eizenga, Andrea Guarracino, Benedict Paten, Erik Garrison, Miquel Moreto**. ["Optimal gap-affine alignment in O(s) space"](https://doi.org/10.1093/bioinformatics/btad074). Bioinformatics, 2023. diff --git a/src/common/wflign/deps/WFA2-lib/VERSION.txt b/src/common/wflign/deps/WFA2-lib/VERSION.txt index e70ef1dd..5c69a91b 100644 --- a/src/common/wflign/deps/WFA2-lib/VERSION.txt +++ b/src/common/wflign/deps/WFA2-lib/VERSION.txt @@ -1 +1 @@ -v2.3 +v2.3 \ No newline at end of file diff --git a/src/common/wflign/deps/WFA2-lib/alignment/cigar.c b/src/common/wflign/deps/WFA2-lib/alignment/cigar.c index 4c4efe39..131fcff2 100644 --- a/src/common/wflign/deps/WFA2-lib/alignment/cigar.c +++ b/src/common/wflign/deps/WFA2-lib/alignment/cigar.c @@ -32,30 +32,58 @@ #include "utils/commons.h" #include "cigar.h" +/* + * SAM CIGAR Operations + */ +#define SAM_CIGAR_MATCH 0 +#define SAM_CIGAR_INS 1 +#define SAM_CIGAR_DEL 2 +#define SAM_CIGAR_N_SKIP 3 +#define SAM_CIGAR_EQ 7 +#define SAM_CIGAR_X 8 +/* ... */ +#define SAM_CIGAR_NA 15 + +const uint8_t sam_cigar_lut[256] = +{ + [0 ... 255] = SAM_CIGAR_NA, + ['M'] = SAM_CIGAR_MATCH, + ['I'] = SAM_CIGAR_INS, + ['D'] = SAM_CIGAR_DEL, + ['N'] = SAM_CIGAR_N_SKIP, + ['='] = SAM_CIGAR_EQ, + ['X'] = SAM_CIGAR_X, +}; + /* * Setup */ cigar_t* cigar_new( - const int max_operations, - mm_allocator_t* const mm_allocator) { + const int max_operations) { // Allocate - cigar_t* const cigar = mm_allocator_alloc(mm_allocator,cigar_t); - // Allocate buffer + cigar_t* const cigar = malloc(sizeof(cigar_t)); + // Allocate alignment-operations buffer cigar->max_operations = max_operations; - cigar->operations = mm_allocator_malloc(mm_allocator,cigar->max_operations); + cigar->operations = malloc(cigar->max_operations); cigar->begin_offset = 0; cigar->end_offset = 0; cigar->score = INT32_MIN; - // MM - cigar->mm_allocator = mm_allocator; + // CIGAR + cigar->cigar_buffer = calloc(max_operations,sizeof(uint32_t)); // Return return cigar; } void cigar_clear( cigar_t* const cigar) { + // Alignment operations cigar->begin_offset = 0; cigar->end_offset = 0; + // Score and end position cigar->score = INT32_MIN; + cigar->end_v = -1; + cigar->end_h = -1; + // CIGAR + cigar->cigar_length = 0; } void cigar_resize( cigar_t* const cigar, @@ -63,23 +91,27 @@ void cigar_resize( // Check maximum operations if (max_operations > cigar->max_operations) { cigar->max_operations = max_operations; - mm_allocator_free(cigar->mm_allocator,cigar->operations); // Free - cigar->operations = mm_allocator_malloc( - cigar->mm_allocator,max_operations); // Allocate + free(cigar->operations); // Free + free(cigar->cigar_buffer); // Free + cigar->operations = malloc(max_operations); // Allocate + cigar->cigar_buffer = calloc(max_operations,sizeof(uint32_t)); // Allocate } - cigar->begin_offset = 0; - cigar->end_offset = 0; - cigar->score = INT32_MIN; + cigar_clear(cigar); } void cigar_free( cigar_t* const cigar) { - mm_allocator_free(cigar->mm_allocator,cigar->operations); - mm_allocator_free(cigar->mm_allocator,cigar); + free(cigar->operations); + free(cigar->cigar_buffer); + free(cigar); } /* * Accessors */ -int cigar_get_matches( +bool cigar_is_null( + cigar_t* const cigar) { + return (cigar->begin_offset >= cigar->end_offset); +} +int cigar_count_matches( cigar_t* const cigar) { int i, num_matches=0; for (i=cigar->begin_offset;iend_offset;++i) { @@ -87,42 +119,121 @@ int cigar_get_matches( } return num_matches; } -void cigar_add_mismatches( - char* const pattern, - const int pattern_length, - char* const text, - const int text_length, - cigar_t* const cigar) { - // Refine adding mismatches - int i, p=0, t=0; - for (i=cigar->begin_offset;iend_offset;++i) { - // Check limits - if (p >= pattern_length || t >= text_length) break; - switch (cigar->operations[i]) { - case 'M': - cigar->operations[i] = (pattern[p]==text[t]) ? 'M' : 'X'; - ++p; ++t; - break; - case 'I': - ++t; - break; - case 'D': - ++p; - break; - default: - fprintf(stderr,"[CIGAR] Wrong edit operation\n"); - exit(1); - break; +void cigar_append_forward( + cigar_t* const cigar_dst, + cigar_t* const cigar_src) { + // Parameters + const int cigar_length = cigar_src->end_offset - cigar_src->begin_offset; + char* const operations_src = cigar_src->operations + cigar_src->begin_offset; + char* const operations_dst = cigar_dst->operations + cigar_dst->end_offset; + // Append forward + memcpy(operations_dst,operations_src,cigar_length); + // Update offset + cigar_dst->end_offset += cigar_length; +} +void cigar_append_reverse( + cigar_t* const cigar_dst, + cigar_t* const cigar_src) { + // Parameters + const int begin_offset = cigar_src->begin_offset; + const int end_offset = cigar_src->end_offset; + const int cigar_length = end_offset - begin_offset; + char* const operations_src = cigar_src->operations + begin_offset; + char* const operations_dst = cigar_dst->operations + cigar_dst->end_offset; + // Append reverse + int i; + for (i=0;iend_offset += cigar_length; +} +void cigar_append_deletion( + cigar_t* const cigar, + const int length) { + // Append deletions + char* const operations = cigar->operations + cigar->end_offset; + int i; + for (i=0;iend_offset += length; +} +void cigar_append_insertion( + cigar_t* const cigar, + const int length) { + // Append insertions + char* const operations = cigar->operations + cigar->end_offset; + int i; + for (i=0;iend_offset += length; +} +/* + * SAM-compliant CIGAR + */ +void cigar_compute_CIGAR( + cigar_t* const cigar, + const bool show_mismatches) { + // Prepare CIGAR (SAM compliant) + if (cigar->cigar_length==0 || cigar->has_misms!=show_mismatches) { + const char* const operations = cigar->operations; + const int begin_offset = cigar->begin_offset; + const int end_offset = cigar->end_offset; + // Check null CIGAR + if (begin_offset >= end_offset) { + cigar->cigar_length = 0; + return; + } + // Generate CIGAR + uint32_t* const cigar_buffer = cigar->cigar_buffer; + int cigar_length = 0; + char last_op = operations[begin_offset]; + uint32_t last_op_len = 1; + int i; + for (i=begin_offset+1;ihas_misms = show_mismatches; + cigar->cigar_length = cigar_length; } - while (p < pattern_length) { cigar->operations[i++] = 'D'; ++p; }; - while (t < text_length) { cigar->operations[i++] = 'I'; ++t; }; - cigar->end_offset = i; - cigar->operations[cigar->end_offset] = '\0'; - // // DEBUG - // printf("Score=%ld\nPath-length=%" PRIu64 "\nCIGAR=%s\n", - // gaba_alignment->score,gaba_alignment->plen, - // cigar->operations); +} +void cigar_get_CIGAR( + cigar_t* const cigar, + const bool show_mismatches, + uint32_t** const cigar_buffer, + int* const cigar_length) { + // Compute CIGAR + cigar_compute_CIGAR(cigar,show_mismatches); + // Return + *cigar_buffer = cigar->cigar_buffer; + *cigar_length = cigar->cigar_length; } /* * Score @@ -136,7 +247,9 @@ int cigar_score_edit( case 'X': case 'D': case 'I': ++score; break; - default: return INT_MIN; + default: + fprintf(stderr,"[CIGAR] Computing CIGAR score: Unknown operation\n"); + exit(1); } } return score; @@ -151,7 +264,9 @@ int cigar_score_gap_linear( case 'X': score -= penalties->mismatch; break; case 'I': score -= penalties->indel; break; case 'D': score -= penalties->indel; break; - default: return INT_MIN; + default: + fprintf(stderr,"[CIGAR] Computing CIGAR score: Unknown operation\n"); + exit(1); } } return score; @@ -183,7 +298,7 @@ int cigar_score_gap_affine( } return score; } -int cigar_score_gap_affine2p_get_operations_score( +int cigar_score_gap_affine2p_score_op( const char operation, const int length, affine2p_penalties_t* const penalties) { @@ -212,15 +327,14 @@ int cigar_score_gap_affine2p( for (i=cigar->begin_offset;iend_offset;++i) { // Account for operation if (cigar->operations[i] != last_op && last_op != '\0') { - score -= cigar_score_gap_affine2p_get_operations_score(last_op,op_length,penalties); + score -= cigar_score_gap_affine2p_score_op(last_op,op_length,penalties); op_length = 0; } - // Add operation last_op = cigar->operations[i]; ++op_length; } // Account for last operation - score -= cigar_score_gap_affine2p_get_operations_score(last_op,op_length,penalties); + score -= cigar_score_gap_affine2p_score_op(last_op,op_length,penalties); return score; } /* @@ -256,41 +370,247 @@ void cigar_copy( cigar_src->operations+cigar_src->begin_offset, cigar_src->end_offset-cigar_src->begin_offset); } -void cigar_append( - cigar_t* const cigar_dst, - cigar_t* const cigar_src) { - // Append - const int cigar_length = cigar_src->end_offset - cigar_src->begin_offset; - char* const operations_src = cigar_src->operations + cigar_src->begin_offset; - char* const operations_dst = cigar_dst->operations + cigar_dst->end_offset; - memcpy(operations_dst,operations_src,cigar_length); - // Update offset - cigar_dst->end_offset += cigar_length; +void cigar_discover_mismatches( + char* const pattern, + const int pattern_length, + char* const text, + const int text_length, + cigar_t* const cigar) { + // Refine adding mismatches + int i, p=0, t=0; + for (i=cigar->begin_offset;iend_offset;++i) { + // Check limits + if (p >= pattern_length || t >= text_length) break; + switch (cigar->operations[i]) { + case 'M': + cigar->operations[i] = (pattern[p]==text[t]) ? 'M' : 'X'; + ++p; ++t; + break; + case 'I': + ++t; + break; + case 'D': + ++p; + break; + default: + fprintf(stderr,"[CIGAR] Wrong edit operation\n"); + exit(1); + break; + } + } + while (p < pattern_length) { cigar->operations[i++] = 'D'; ++p; }; + while (t < text_length) { cigar->operations[i++] = 'I'; ++t; }; + cigar->end_offset = i; + cigar->operations[cigar->end_offset] = '\0'; + // // DEBUG + // printf("Score=%ld\nPath-length=%" PRIu64 "\nCIGAR=%s\n", + // gaba_alignment->score,gaba_alignment->plen, + // cigar->operations); } -void cigar_append_deletion( +/* + * Maxtrim + * Reduce the CIGAR to the maximal scoring sequence, starting from + * the beginning, under a given distance function + * + */ +bool cigar_maxtrim_gap_linear( cigar_t* const cigar, - const int length) { - // Append deletions - char* const operations = cigar->operations + cigar->end_offset; - int i; - for (i=0;ioperations; + const int begin_offset = cigar->begin_offset; + const int end_offset = cigar->end_offset; + const int match_score = (penalties->match!=0) ? penalties->match : -1; + // Max-score + int max_score = 0, max_score_offset = begin_offset, max_end_v = 0, max_end_h = 0; + // Traverse all cigar + int score = 0, end_v = 0, end_h = 0, i; + for (i=begin_offset;imismatch; + ++end_v; ++end_h; + break; + case 'I': + score -= penalties->indel; + ++end_h; + break; + case 'D': + score -= penalties->indel; + ++end_v; + break; + } + // Compare max + if (max_score < score) { + max_score = score; + max_score_offset = i; + max_end_v = end_v; + max_end_h = end_h; + } } - // Update offset - cigar->end_offset += length; + // Keep the max-scoring part of the cigar + const bool cigar_trimmed = (max_score_offset != end_offset-1); + if (max_score == 0) { + cigar_clear(cigar); + } else { + cigar->operations[max_score_offset+1] = '\0'; + cigar->end_offset = max_score_offset + 1; + cigar->score = max_score; + cigar->end_v = max_end_v; + cigar->end_h = max_end_h; + } + // Return + return cigar_trimmed; } -void cigar_append_insertion( +bool cigar_maxtrim_gap_affine( cigar_t* const cigar, - const int length) { - // Append insertions - char* const operations = cigar->operations + cigar->end_offset; + affine_penalties_t* const penalties) { + // Parameters + const char* const operations = cigar->operations; + const int begin_offset = cigar->begin_offset; + const int end_offset = cigar->end_offset; + const int match_score = (penalties->match!=0) ? penalties->match : -1; + // Max-score + int max_score = 0, max_score_offset = begin_offset, max_end_v = 0, max_end_h = 0; + // Traverse all cigar + char last_op = '\0'; + int score = 0, end_v = 0, end_h = 0, i; + for (i=begin_offset;imismatch; + ++end_v; ++end_h; + break; + case 'I': + score -= penalties->gap_extension + ((last_op=='I') ? 0 : penalties->gap_opening); + ++end_h; + break; + case 'D': + score -= penalties->gap_extension + ((last_op=='D') ? 0 : penalties->gap_opening); + ++end_v; + break; + } + last_op = operations[i]; + // Compare max + if (max_score < score) { + max_score = score; + max_score_offset = i; + max_end_v = end_v; + max_end_h = end_h; + } + } + // Keep the max-scoring part of the cigar + const bool cigar_trimmed = (max_score_offset != end_offset-1); + if (max_score == 0) { + cigar_clear(cigar); + } else { + cigar->operations[max_score_offset+1] = '\0'; + cigar->end_offset = max_score_offset + 1; + cigar->score = max_score; + cigar->end_v = max_end_v; + cigar->end_h = max_end_h; + } + // Return + return cigar_trimmed; +} +int cigar_maxtrim_gap_affine2p_score_op( + const char operation, + const int length, + affine2p_penalties_t* const penalties, + int* const end_v, + int* const end_h) { + switch (operation) { + case 'M': { + *end_v += length; *end_h += length; + const int match_score = (penalties->match!=0) ? penalties->match : -1; + return match_score*length; + } + case 'X': + *end_v += length; *end_h += length; + return penalties->mismatch*length; + case 'D': { + *end_v += length; + const int score1 = penalties->gap_opening1 + penalties->gap_extension1*length; + const int score2 = penalties->gap_opening2 + penalties->gap_extension2*length; + return MIN(score1,score2); + } + case 'I': { + *end_h += length; + const int score1 = penalties->gap_opening1 + penalties->gap_extension1*length; + const int score2 = penalties->gap_opening2 + penalties->gap_extension2*length; + return MIN(score1,score2); + } + default: + fprintf(stderr,"[CIGAR] Computing CIGAR score: Unknown operation\n"); + exit(1); + } +} +bool cigar_maxtrim_gap_affine2p( + cigar_t* const cigar, + affine2p_penalties_t* const penalties) { + // Parameters + const char* const operations = cigar->operations; + const int begin_offset = cigar->begin_offset; + const int end_offset = cigar->end_offset; + if (begin_offset >= end_offset) return false; + // Max-score + int max_score = 0, max_score_offset = begin_offset, max_end_v = 0, max_end_h = 0; + // Traverse all cigar + char last_op = '\0'; + int score = 0, end_v = 0, end_h = 0, op_length = 0; int i; - for (i=0;iend_offset += length; + // Account for last operation + score -= cigar_maxtrim_gap_affine2p_score_op(last_op,op_length,penalties,&end_v,&end_h); + if (max_score < score) { + max_score = score; + max_score_offset = end_offset - 1; + max_end_v = end_v; + max_end_h = end_h; + } + // Keep the max-scoring part of the cigar + const bool cigar_trimmed = (max_score_offset != end_offset-1); + if (max_score == 0) { + cigar_clear(cigar); + } else { + cigar->operations[max_score_offset+1] = '\0'; + cigar->end_offset = max_score_offset + 1; + cigar->score = max_score; + cigar->end_v = max_end_v; + cigar->end_h = max_end_h; + } + // Return + return cigar_trimmed; } +/* + * Check + */ bool cigar_check_alignment( FILE* const stream, const char* const pattern, @@ -370,78 +690,102 @@ void cigar_print( FILE* const stream, cigar_t* const cigar, const bool print_matches) { - // Check null CIGAR - if (cigar->begin_offset >= cigar->end_offset) return; - // Print operations - char last_op = cigar->operations[cigar->begin_offset]; - int last_op_length = 1; - int i; - for (i=cigar->begin_offset+1;iend_offset;++i) { - if (cigar->operations[i]==last_op) { - ++last_op_length; - } else { - if (print_matches || last_op != 'M') { - fprintf(stream,"%d%c",last_op_length,last_op); - } - last_op = cigar->operations[i]; - last_op_length = 1; - } - } - if (print_matches || last_op != 'M') { - fprintf(stream,"%d%c",last_op_length,last_op); - } + // Check null + if (cigar_is_null(cigar)) return; + // Generate and print operations + char* const buffer = malloc(2*(cigar->end_offset-cigar->begin_offset)+10); + cigar_sprint(buffer,cigar,print_matches); + fprintf(stream,"%s",buffer); // Print + // Free + free(buffer); } int cigar_sprint( - char* buffer, + char* const buffer, cigar_t* const cigar, const bool print_matches) { - // Parameters - int pos = 0; - // Check null CIGAR - if (cigar->begin_offset >= cigar->end_offset) { - buffer[pos] = '\0'; - return pos; + // Check null + if (cigar_is_null(cigar)) { + buffer[0] = '\0'; + return 0; } + // Parameters + const char* const operations = cigar->operations; + const int begin_offset = cigar->begin_offset; + const int end_offset = cigar->end_offset; // Print operations - char last_op = cigar->operations[cigar->begin_offset]; + char last_op = operations[begin_offset]; int last_op_length = 1; - int i; - for (i=cigar->begin_offset+1;iend_offset;++i) { - if (cigar->operations[i]==last_op) { + int i, cursor = 0; + for (i=begin_offset+1;ioperations[i]; + last_op = operations[i]; last_op_length = 1; } } if (print_matches || last_op != 'M') { - pos += sprintf(buffer+pos,"%d%c",last_op_length,last_op); + cursor += sprintf(buffer+cursor,"%d%c",last_op_length,last_op); + } + // Return + buffer[cursor] = '\0'; + return cursor; +} +void cigar_print_SAM_CIGAR( + FILE* const stream, + cigar_t* const cigar, + const bool show_mismatches) { + // Check null + if (cigar_is_null(cigar)) return; + // Generate and print operations + char* const buffer = malloc(2*(cigar->end_offset-cigar->begin_offset)); + cigar_sprint_SAM_CIGAR(buffer,cigar,show_mismatches); + fprintf(stream,"%s",buffer); // Print + // Free + free(buffer); +} +int cigar_sprint_SAM_CIGAR( + char* const buffer, + cigar_t* const cigar, + const bool show_mismatches) { + // Get SAM CIGAR + uint32_t* cigar_buffer; + int cigar_length; + cigar_get_CIGAR(cigar,show_mismatches,&cigar_buffer,&cigar_length); + // Print CIGAR-operations + int i, cursor = 0; + for (i=0;i>4, + "MIDN---=X"[cigar_buffer[i]&0xf]); } // Return - buffer[pos] = '\0'; - return pos; + buffer[cursor] = '\0'; + return cursor; } void cigar_print_pretty( FILE* const stream, + cigar_t* const cigar, const char* const pattern, const int pattern_length, const char* const text, - const int text_length, - cigar_t* const cigar, - mm_allocator_t* const mm_allocator) { + const int text_length) { // Parameters char* const operations = cigar->operations; + const int begin_offset = cigar->begin_offset; + const int end_offset = cigar->end_offset; // Allocate alignment buffers - const int max_buffer_length = text_length+pattern_length+1; - char* const pattern_alg = mm_allocator_calloc(mm_allocator,max_buffer_length,char,true); - char* const ops_alg = mm_allocator_calloc(mm_allocator,max_buffer_length,char,true); - char* const text_alg = mm_allocator_calloc(mm_allocator,max_buffer_length,char,true); + const int max_buffer_length = text_length + pattern_length + 1; + char* const mem = calloc(3*max_buffer_length,1); + char* const pattern_alg = mem; + char* const ops_alg = pattern_alg + max_buffer_length; + char* const text_alg = ops_alg + max_buffer_length; // Compute alignment buffers int i, alg_pos = 0, pattern_pos = 0, text_pos = 0; - for (i=cigar->begin_offset;iend_offset;++i) { + for (i=begin_offset;iattributes.memory_mode = wavefront_memory_high; break; } this->attributes.alignment_scope = (alignmentScope==Score) ? compute_score : compute_alignment; - //this->attributes.system.verbose = 2; + // this->attributes.system.verbose = 2; // DEBUG + // this->attributes.plot.enabled = true; // DEBUG this->wfAligner = nullptr; } WFAligner::~WFAligner() { @@ -64,37 +65,54 @@ WFAligner::~WFAligner() { /* * Align End-to-end */ -WFAligner::AlignmentStatus WFAligner::alignEnd2EndLambda( +WFAligner::AlignmentStatus WFAligner::alignEnd2End( + const char* const pattern, const int patternLength, + const char* const text, const int textLength) { // Configure wavefront_aligner_set_alignment_end_to_end(wfAligner); - // Align (using custom matching function) - return (WFAligner::AlignmentStatus) wavefront_align(wfAligner,NULL,patternLength,NULL,textLength); + // Align + return (WFAligner::AlignmentStatus) wavefront_align( + wfAligner,pattern,patternLength,text,textLength); } WFAligner::AlignmentStatus WFAligner::alignEnd2End( - const char* const pattern, + const std::string& pattern, + const std::string& text) { + // Delegate + return alignEnd2End(pattern.c_str(),pattern.length(),text.c_str(),text.length()); +} +WFAligner::AlignmentStatus WFAligner::alignEnd2End( + const uint8_t* const pattern, const int patternLength, - const char* const text, + const uint8_t* const text, const int textLength) { // Configure wavefront_aligner_set_alignment_end_to_end(wfAligner); // Align - return (WFAligner::AlignmentStatus) wavefront_align(wfAligner,pattern,patternLength,text,textLength); + return (WFAligner::AlignmentStatus) wavefront_align_packed2bits( + wfAligner,pattern,patternLength,text,textLength); } WFAligner::AlignmentStatus WFAligner::alignEnd2End( - std::string& pattern, - std::string& text) { - // Delegate - return alignEnd2End(pattern.c_str(),pattern.length(),text.c_str(),text.length()); + int (*matchFunct)(int,int,void*), + void* matchFunctArguments, + const int patternLength, + const int textLength) { + // Configure + wavefront_aligner_set_alignment_end_to_end(wfAligner); + // Align (using custom matching function) + return (WFAligner::AlignmentStatus) wavefront_align_lambda( + wfAligner,matchFunct,matchFunctArguments,patternLength,textLength); } /* * Align Ends-free */ -WFAligner::AlignmentStatus WFAligner::alignEndsFreeLambda( +WFAligner::AlignmentStatus WFAligner::alignEndsFree( + const char* const pattern, const int patternLength, const int patternBeginFree, const int patternEndFree, + const char* const text, const int textLength, const int textBeginFree, const int textEndFree) { @@ -102,15 +120,28 @@ WFAligner::AlignmentStatus WFAligner::alignEndsFreeLambda( wavefront_aligner_set_alignment_free_ends(wfAligner, patternBeginFree,patternEndFree, textBeginFree,textEndFree); - // Align (using custom matching function) - return (WFAligner::AlignmentStatus) wavefront_align(wfAligner,NULL,patternLength,NULL,textLength); + // Align + return (WFAligner::AlignmentStatus) wavefront_align( + wfAligner,pattern,patternLength,text,textLength); } WFAligner::AlignmentStatus WFAligner::alignEndsFree( - const char* const pattern, + const std::string& pattern, + const int patternBeginFree, + const int patternEndFree, + const std::string& text, + const int textBeginFree, + const int textEndFree) { + // Delegate + return alignEndsFree( + pattern.c_str(),pattern.length(),patternBeginFree,patternEndFree, + text.c_str(),text.length(),textBeginFree,textEndFree); +} +WFAligner::AlignmentStatus WFAligner::alignEndsFree( + const uint8_t* const pattern, const int patternLength, const int patternBeginFree, const int patternEndFree, - const char* const text, + const uint8_t* const text, const int textLength, const int textBeginFree, const int textEndFree) { @@ -119,28 +150,67 @@ WFAligner::AlignmentStatus WFAligner::alignEndsFree( patternBeginFree,patternEndFree, textBeginFree,textEndFree); // Align - return (WFAligner::AlignmentStatus) wavefront_align(wfAligner,pattern,patternLength,text,textLength); + return (WFAligner::AlignmentStatus) wavefront_align_packed2bits( + wfAligner,pattern,patternLength,text,textLength); } WFAligner::AlignmentStatus WFAligner::alignEndsFree( - std::string& pattern, + int (*matchFunct)(int,int,void*), + void* matchFunctArguments, + const int patternLength, const int patternBeginFree, const int patternEndFree, - std::string& text, + const int textLength, const int textBeginFree, const int textEndFree) { - // Delegate - return alignEndsFree( - pattern.c_str(),pattern.length(), + // Configure + wavefront_aligner_set_alignment_free_ends(wfAligner, patternBeginFree,patternEndFree, - text.c_str(),text.length(), textBeginFree,textEndFree); + // Align (using custom matching function) + return (WFAligner::AlignmentStatus) wavefront_align_lambda( + wfAligner,matchFunct,matchFunctArguments,patternLength,textLength); } /* - * Alignment resume + * Align Extension */ -WFAligner::AlignmentStatus WFAligner::alignResume() { - // Resume alignment - return (WFAligner::AlignmentStatus) wavefront_align_resume(wfAligner); +WFAligner::AlignmentStatus WFAligner::alignExtension( + const char* const pattern, + const int patternLength, + const char* const text, + const int textLength) { + // Configure + wavefront_aligner_set_alignment_extension(wfAligner); + // Align + return (WFAligner::AlignmentStatus) wavefront_align( + wfAligner,pattern,patternLength,text,textLength); +} +WFAligner::AlignmentStatus WFAligner::alignExtension( + std::string& pattern, + std::string& text) { + // Delegate + return alignExtension(pattern.c_str(),pattern.length(),text.c_str(),text.length()); +} +WFAligner::AlignmentStatus WFAligner::alignExtension( + const uint8_t* const pattern, + const int patternLength, + const uint8_t* const text, + const int textLength) { + // Configure + wavefront_aligner_set_alignment_extension(wfAligner); + // Align + return (WFAligner::AlignmentStatus) wavefront_align_packed2bits( + wfAligner,pattern,patternLength,text,textLength); +} +WFAligner::AlignmentStatus WFAligner::alignExtension( + int (*matchFunct)(int,int,void*), + void* matchFunctArguments, + const int patternLength, + const int textLength) { + // Configure + wavefront_aligner_set_alignment_extension(wfAligner); + // Align (using custom matching function) + return (WFAligner::AlignmentStatus) wavefront_align_lambda( + wfAligner,matchFunct,matchFunctArguments,patternLength,textLength); } /* * Heuristics @@ -189,21 +259,12 @@ void WFAligner::setHeuristicZDrop( wavefront_aligner_set_heuristic_zdrop( wfAligner,zdrop,steps_between_cutoffs); } -/* - * Custom extend-match function (lambda) - */ -void WFAligner::setMatchFunct( - int (*matchFunct)(int,int,void*), - void* matchFunctArguments) { - wavefront_aligner_set_match_funct(wfAligner,matchFunct,matchFunctArguments); -} /* * Limits */ -void WFAligner::setMaxAlignmentScore( - const int maxAlignmentScore) { - wavefront_aligner_set_max_alignment_score( - wfAligner,maxAlignmentScore); +void WFAligner::setMaxAlignmentSteps( + const int maxAlignmentSteps) { + wavefront_aligner_set_max_alignment_steps(wfAligner,maxAlignmentSteps); } void WFAligner::setMaxMemory( const uint64_t maxMemoryResident, @@ -212,46 +273,77 @@ void WFAligner::setMaxMemory( } // Parallelization void WFAligner::setMaxNumThreads( - const int maxNumThreads) { - wavefront_aligner_set_max_num_threads(wfAligner, maxNumThreads); -} -void WFAligner::setMinOffsetsPerThread( - const int minOffsetsPerThread) { - wavefront_aligner_set_min_offsets_per_thread(wfAligner, minOffsetsPerThread); + const int maxNumThreads) { + wavefront_aligner_set_max_num_threads(wfAligner, maxNumThreads); } /* * Accessors */ -int WFAligner::getAlignmentScore() { - return wfAligner->cigar->score; -} int WFAligner::getAlignmentStatus() { return wfAligner->align_status.status; } -void WFAligner::getAlignmentCigar( +int WFAligner::getAlignmentScore() { + return wfAligner->cigar->score; +} +void WFAligner::getAlignment( char** const cigarOperations, int* cigarLength) { *cigarOperations = wfAligner->cigar->operations + wfAligner->cigar->begin_offset; *cigarLength = wfAligner->cigar->end_offset - wfAligner->cigar->begin_offset; } -std::string WFAligner::getAlignmentCigar() { - // Fetch CIGAR - char* buffer; - int bufferLength; - getAlignmentCigar(&buffer,&bufferLength); +std::string WFAligner::getAlignment() { + // Fetch Alignment + char* const buffer = wfAligner->cigar->operations + wfAligner->cigar->begin_offset; + const int length = wfAligner->cigar->end_offset - wfAligner->cigar->begin_offset; // Create string and return - return std::string(buffer,bufferLength); + return std::string(buffer,length); +} +void WFAligner::getCIGAR( + const bool showMismatches, + uint32_t** const cigarOperations, + int* const numCigarOperations) { + cigar_get_CIGAR(wfAligner->cigar,showMismatches,cigarOperations,numCigarOperations); +} +std::string WFAligner::getCIGAR( + const bool showMismatches) { + // Check length + const int alignmentLength = wfAligner->cigar->end_offset - wfAligner->cigar->begin_offset; + if (alignmentLength <= 0) return std::string(); + // Allocate + char* const buffer = new char[2*alignmentLength]; + const int bufferLength = cigar_sprint_SAM_CIGAR(buffer,wfAligner->cigar,showMismatches); + // Create string + std::string cigarString = std::string(buffer,bufferLength); + // Free & return + delete[] buffer; + return cigarString; } /* - * Misc + * Display */ -char* WFAligner::strError( - const int wfErrorCode) { - return wavefront_align_strerror(wfErrorCode); +void WFAligner::printPretty( + FILE* const stream, + const char* const pattern, + const int patternLength, + const char* const text, + const int textLength) { + cigar_print_pretty(stream,wfAligner->cigar,pattern,patternLength,text,textLength); } -void WFAligner::setVerbose( - const int verbose) { - wfAligner->system.verbose = verbose; +/* + * Misc + */ +char* WFAligner::strStatus( + const WFAligner::AlignmentStatus status) { + return wavefront_align_strerror((int)status); +} +void WFAligner::debugTag( + char* const debugTag) { + wfAligner->align_mode_tag = debugTag; + if (wfAligner->bialigner != NULL) { + wfAligner->bialigner->wf_forward->align_mode_tag = debugTag; + wfAligner->bialigner->wf_reverse->align_mode_tag = debugTag; + wfAligner->bialigner->wf_base->align_mode_tag = debugTag; + } } /* * Indel Aligner (a.k.a Longest Common Subsequence - LCS) diff --git a/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp b/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp index 8da82bbc..fd844ba2 100644 --- a/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp +++ b/src/common/wflign/deps/WFA2-lib/bindings/cpp/WFAligner.hpp @@ -59,49 +59,86 @@ class WFAligner { Alignment, }; enum AlignmentStatus { - StatusSuccessful = WF_STATUS_SUCCESSFUL, - StatusUnfeasible = WF_STATUS_UNFEASIBLE, - StatusMaxScoreReached = WF_STATUS_MAX_SCORE_REACHED, + // OK Status (>=0) + StatusAlgCompleted = WF_STATUS_ALG_COMPLETED, + StatusAlgPartial = WF_STATUS_ALG_PARTIAL, + // FAILED Status (<0) + StatusMaxStepsReached = WF_STATUS_MAX_STEPS_REACHED, StatusOOM = WF_STATUS_OOM, }; // Align End-to-end - AlignmentStatus alignEnd2EndLambda( - const int patternLength, - const int textLength); - AlignmentStatus alignEnd2End( + AlignmentStatus alignEnd2End( // Regular ASCII Sequences const char* const pattern, const int patternLength, const char* const text, const int textLength); - AlignmentStatus alignEnd2End( - std::string& pattern, - std::string& text); + AlignmentStatus alignEnd2End( // String ASCII Sequences + const std::string& pattern, + const std::string& text); + AlignmentStatus alignEnd2End( // 2bits-Packed Sequences + const uint8_t* const pattern, + const int patternLength, + const uint8_t* const text, + const int textLength); + AlignmentStatus alignEnd2End( // Lambda Sequence + int (*matchFunct)(int,int,void*), + void* matchFunctArguments, + const int patternLength, + const int textLength); // Align Ends-free - AlignmentStatus alignEndsFreeLambda( + AlignmentStatus alignEndsFree( // Regular ASCII Sequences + const char* const pattern, const int patternLength, const int patternBeginFree, const int patternEndFree, + const char* const text, const int textLength, const int textBeginFree, const int textEndFree); - AlignmentStatus alignEndsFree( - const char* const pattern, + AlignmentStatus alignEndsFree( // String ASCII Sequences + const std::string& pattern, + const int patternBeginFree, + const int patternEndFree, + const std::string& text, + const int textBeginFree, + const int textEndFree); + AlignmentStatus alignEndsFree( // 2bits-Packed Sequences + const uint8_t* const pattern, const int patternLength, const int patternBeginFree, const int patternEndFree, - const char* const text, + const uint8_t* const text, const int textLength, const int textBeginFree, const int textEndFree); - AlignmentStatus alignEndsFree( - std::string& pattern, + AlignmentStatus alignEndsFree( // Lambda Sequence + int (*matchFunct)(int,int,void*), + void* matchFunctArguments, + const int patternLength, const int patternBeginFree, const int patternEndFree, - std::string& text, + const int textLength, const int textBeginFree, const int textEndFree); - // Alignment resume - AlignmentStatus alignResume(); + // Alignment Extension + AlignmentStatus alignExtension( // Regular ASCII Sequences + const char* const pattern, + const int patternLength, + const char* const text, + const int textLength); + AlignmentStatus alignExtension( // String ASCII Sequences + std::string& pattern, + std::string& text); + AlignmentStatus alignExtension( // 2bits-Packed Sequences + const uint8_t* const pattern, + const int patternLength, + const uint8_t* const text, + const int textLength); + AlignmentStatus alignExtension( // Lambda Sequence + int (*matchFunct)(int,int,void*), + void* matchFunctArguments, + const int patternLength, + const int textLength); // Heuristics void setHeuristicNone(); void setHeuristicBandedStatic( @@ -125,33 +162,40 @@ class WFAligner { void setHeuristicZDrop( const int zdrop, const int steps_between_cutoffs = 1); - // Custom extend-match function (lambda) - void setMatchFunct( - int (*matchFunct)(int,int,void*), - void* matchFunctArguments); // Limits - void setMaxAlignmentScore( - const int maxAlignmentScore); + void setMaxAlignmentSteps( + const int maxAlignmentSteps); void setMaxMemory( const uint64_t maxMemoryResident, const uint64_t maxMemoryAbort); // Parallelization void setMaxNumThreads( const int maxNumThreads); - void setMinOffsetsPerThread( - const int minOffsetsPerThread); // Accessors - int getAlignmentScore(); int getAlignmentStatus(); - void getAlignmentCigar( + int getAlignmentScore(); + void getAlignment( char** const cigarOperations, int* cigarLength); - std::string getAlignmentCigar(); + std::string getAlignment(); + void getCIGAR( + const bool showMismatches, + uint32_t** const cigarOperations, + int* const numCigarOperations); + std::string getCIGAR( + const bool showMismatches); + // Display + void printPretty( + FILE* const stream, + const char* const pattern, + const int patternLength, + const char* const text, + const int textLength); // Misc - char* strError( - const int wfErrorCode); - void setVerbose( - const int verbose); + char* strStatus( + const AlignmentStatus status); + void debugTag( + char* const debugTag); protected: wavefront_aligner_attr_t attributes; wavefront_aligner_t* wfAligner; diff --git a/src/common/wflign/deps/WFA2-lib/examples/Makefile b/src/common/wflign/deps/WFA2-lib/examples/Makefile index 34736835..110b5eff 100644 --- a/src/common/wflign/deps/WFA2-lib/examples/Makefile +++ b/src/common/wflign/deps/WFA2-lib/examples/Makefile @@ -10,6 +10,9 @@ FOLDER_BIN=bin ############################################################################### LIB_WFA=$(FOLDER_LIB)/libwfa.a LIBS=-fopenmp -lm +ifeq ($(UNAME), Linux) + LIBS+=-lrt +endif all: setup examples_c examples_cpp diff --git a/src/common/wflign/deps/WFA2-lib/examples/wfa_basic.c b/src/common/wflign/deps/WFA2-lib/examples/wfa_basic.c index 1b3751ff..cf8ff802 100644 --- a/src/common/wflign/deps/WFA2-lib/examples/wfa_basic.c +++ b/src/common/wflign/deps/WFA2-lib/examples/wfa_basic.c @@ -53,9 +53,8 @@ int main(int argc,char* argv[]) { fprintf(stderr," TEXT %s\n",text); fprintf(stderr," SCORE (RE)COMPUTED %d\n", cigar_score_gap_affine(wf_aligner->cigar,&attributes.affine_penalties)); - cigar_print_pretty(stderr, - pattern,strlen(pattern),text,strlen(text), - wf_aligner->cigar,wf_aligner->mm_allocator); + cigar_print_pretty(stderr,wf_aligner->cigar, + pattern,strlen(pattern),text,strlen(text)); // Free wavefront_aligner_delete(wf_aligner); } diff --git a/src/common/wflign/deps/WFA2-lib/examples/wfa_bindings.cpp b/src/common/wflign/deps/WFA2-lib/examples/wfa_bindings.cpp index feec4400..44f686c1 100644 --- a/src/common/wflign/deps/WFA2-lib/examples/wfa_bindings.cpp +++ b/src/common/wflign/deps/WFA2-lib/examples/wfa_bindings.cpp @@ -48,7 +48,7 @@ int main(int argc,char* argv[]) { cout << "WFA-Alignment returns score " << aligner.getAlignmentScore() << endl; // Print CIGAR - string cigar = aligner.getAlignmentCigar(); + string cigar = aligner.getAlignment(); cout << "PATTERN: " << pattern << endl; cout << "TEXT: " << text << endl; cout << "CIGAR: " << cigar << endl; diff --git a/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp b/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp index 0fc60095..71f2a72e 100644 --- a/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp +++ b/src/common/wflign/deps/WFA2-lib/examples/wfa_lambda.cpp @@ -56,13 +56,12 @@ int match_function( int main(int argc,char* argv[]) { // Create a WFAligner WFAlignerGapAffine aligner(1,0,1,WFAligner::Alignment,WFAligner::MemoryHigh); - aligner.setMatchFunct(match_function,NULL); // Align - aligner.alignEnd2EndLambda(patternLength,textLength); + aligner.alignEnd2End(match_function,NULL,patternLength,textLength); cout << "WFA-Alignment returns score " << aligner.getAlignmentScore() << endl; // Print CIGAR - string cigar = aligner.getAlignmentCigar(); + string cigar = aligner.getAlignment(); cout << "PATTERN: " << pattern << endl; cout << "TEXT: " << text << endl; cout << "CIGAR: " << cigar << endl; diff --git a/src/common/wflign/deps/WFA2-lib/img/wfa.endsfree.png b/src/common/wflign/deps/WFA2-lib/img/wfa.endsfree.png new file mode 100644 index 0000000000000000000000000000000000000000..5eac1ee1553355bacdb23e92959816b54eadbcf5 GIT binary patch literal 68149 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 literal 0 HcmV?d00001 diff --git a/src/common/wflign/deps/WFA2-lib/scripts/wfa.alg.cmp.score.sh b/src/common/wflign/deps/WFA2-lib/scripts/wfa.alg.cmp.score.sh index 1ccc172a..ead94945 100755 --- a/src/common/wflign/deps/WFA2-lib/scripts/wfa.alg.cmp.score.sh +++ b/src/common/wflign/deps/WFA2-lib/scripts/wfa.alg.cmp.score.sh @@ -10,5 +10,5 @@ FILE1=$1 FILE2=$2 # Compare -diff <( awk '{print $1}' $FILE1 ) <( awk '{print $1}' $FILE2 ) +diff <( awk '{print $1}' $FILE1 ) <( awk '{print $1}' $FILE2 ) diff --git a/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c b/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c index e0712d6b..96831937 100644 --- a/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c +++ b/src/common/wflign/deps/WFA2-lib/system/mm_allocator.c @@ -612,3 +612,6 @@ void mm_allocator_print( mm_allocator_print_allocator_requests(stream,mm_allocator,false); } } + + + diff --git a/src/common/wflign/deps/WFA2-lib/system/mm_stack.c b/src/common/wflign/deps/WFA2-lib/system/mm_stack.c index 5a0ae46a..abb86d21 100644 --- a/src/common/wflign/deps/WFA2-lib/system/mm_stack.c +++ b/src/common/wflign/deps/WFA2-lib/system/mm_stack.c @@ -266,3 +266,5 @@ void mm_stack_print( fprintf(stream," => Segments.size %" PRIu64 " MB\n",segment_size/(1024*1024)); fprintf(stream," => Memory.available %" PRIu64 " MB\n",num_segments*(segment_size/(1024*1024))); } + + diff --git a/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h b/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h index b2b7c376..55b1b98a 100644 --- a/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h +++ b/src/common/wflign/deps/WFA2-lib/system/profiler_counter.h @@ -33,6 +33,9 @@ #ifndef PROFILER_COUNTER_H_ #define PROFILER_COUNTER_H_ +#include +#include + /* * Counters */ diff --git a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c index 623e8b91..eb25853d 100644 --- a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c +++ b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c @@ -52,7 +52,7 @@ void timer_get_system_time(struct timespec *ts) { ts->tv_sec = mts.tv_sec; ts->tv_nsec = mts.tv_nsec; #else - //clock_gettime(CLOCK_REALTIME,ts); + clock_gettime(CLOCK_REALTIME,ts); #endif } /* diff --git a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h index 5d530382..d3aee5e9 100644 --- a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h +++ b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.h @@ -33,6 +33,7 @@ #ifndef PROFILER_TIMER_H #define PROFILER_TIMER_H +#include #include "profiler_counter.h" /* diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.mem b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.mem index b37ced9d..bb12919d 100644 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.mem +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.mem @@ -1,60 +1,60 @@ -2692 -2704 -2792 -2836 -2952 -3040 -3208 -3300 -3500 -3512 -3512 -3516 -3536 -3724 -3728 -3740 -3772 -3964 -4004 -4132 -4164 -4296 -4632 -4632 -4780 -4784 -4836 -4852 -4852 -5188 -5292 -5840 -6116 -6352 -6996 -7112 -26952 -27212 -28080 -30704 -32172 -35236 -37116 -44296 -48932 -60944 -61132 -72804 -89732 -91368 -130072 -158488 -207416 -218392 -281456 -367248 -414740 -566220 -827568 -1783148 +2736 +2756 +2824 +2852 +2860 +2964 +3296 +3432 +3476 +3544 +3552 +3668 +3672 +3800 +3836 +3876 +3888 +4028 +4092 +4144 +4288 +4524 +4608 +4768 +4892 +5180 +5460 +5988 +5996 +6080 +6260 +6508 +6724 +7568 +10896 +12848 +23296 +23308 +27784 +30844 +32016 +34908 +40044 +44060 +48748 +60992 +61064 +72876 +89752 +91260 +126132 +154608 +207612 +214364 +277644 +367436 +410692 +558932 +827556 +1783444 diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.time b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.time index f42f2e3b..4810920d 100644 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.time +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.check/wfa.utest.log.time @@ -1,21 +1,11 @@ -1.02 s -1.16 s -1.18 s -1.27 s -1.38 s -1.39 s -1.42 s -1.71 s -1.71 s -1.75 s -1.92 s -2.17 s -2.41 s -2.53 s -3.26 s -3.67 s -3.83 s -4.01 s -5.01 s -7.65 s -13.33 s +1.14 s +1.30 s +1.32 s +1.44 s +1.47 s +1.55 s +2.20 s +2.22 s +2.76 s +3.80 s +7.81 s diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh index 707b0dc5..e3efe497 100755 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.cmp.sh @@ -3,11 +3,19 @@ # LICENCE: MIT License # AUTHOR(S): Santiago Marco-Sola # DESCRIPTION: Compares alignments (*.alg) from two folders -# USAGE: ./wfa.utest.cmp.sh wfa_results_folder_1 wfa_results_folder_2 +# USAGE: ./wfa.utest.cmp.sh folder_1 folder_2 [--cmp-performance] # Parameters FOLDER1=$1 FOLDER2=$2 +CMP_PERF=0 +if [[ "$3" == "--cmp-performance" ]] +then + CMP_PERF=1 +fi + +# Innit status OK +STATUS=0 echo "> Comparing $FOLDER1 vs $FOLDER2" for FILE_ALG1 in $FOLDER1/*.alg @@ -21,6 +29,7 @@ do # Check existence if [[ ! -f "$FILE_ALG2" ]] then + STATUS=1 echo "$FILE_ALG2 doesn't exist." continue fi @@ -29,11 +38,27 @@ do then if [[ $(diff <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG1) <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG2)) ]] then + STATUS=1 echo "Error" + continue else - echo "ok" # Only score + STATUS=1 + echo -n "ok" # Only score fi else - echo "OK" + echo -n "OK" + fi + # Stats + if [[ $CMP_PERF == 1 ]] + then + T1=$(grep -m1 "Time.Alignment" $FOLDER1/$PREFIX.log | awk '{print $3" "$4}') + T2=$(grep -m1 "Time.Alignment" $FOLDER2/$PREFIX.log | awk '{print $3" "$4}') + M1=$(grep -m1 "Maximum resident set size" $FOLDER1/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') + M2=$(grep -m1 "Maximum resident set size" $FOLDER2/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') + echo -e "\tTIME($T1,$T2)\tMEM($M1,$M2)" + else + echo fi done + +exit $STATUS diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh deleted file mode 100755 index 60b9f08e..00000000 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.cmp.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -# PROJECT: Wavefront Alignments Algorithms (Unitary Tests) -# LICENCE: MIT License -# AUTHOR(S): Santiago Marco-Sola -# DESCRIPTION: Compares alignments (*.alg) from two folders -# USAGE: ./wfa.utest.performance.cmp.sh wfa_results_folder_1 wfa_results_folder_2 - -# Parameters -FOLDER1=$1 -FOLDER2=$2 - -echo "> Comparing $FOLDER1 vs $FOLDER2" -for FILE_ALG1 in $FOLDER1/*.alg -do - FILENAME=$(basename -- "$FILE_ALG1") - PREFIX=${FILENAME%.*} - FILE_ALG2="$FOLDER2/$FILENAME" - echo -ne "[UTest::$PREFIX]" - if [[ ${#PREFIX} < 15 ]]; then echo -ne " "; fi - echo -ne "\t" - # Check existence - if [[ ! -f "$FILE_ALG2" ]] - then - echo "$FILE_ALG2 doesn't exist." - continue - fi - # Check diff - if [[ $(diff $FILE_ALG1 $FILE_ALG2) ]] - then - if [[ $(diff <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG1) <(awk '{if ($1<0) print -$1; else print $1}' $FILE_ALG2)) ]] - then - echo "Error" - continue - else - echo -n "OK" # Only score - fi - else - echo -n "OK" - fi - # Stats - T1=$(grep -m1 "Time.Alignment" $FOLDER1/$PREFIX.log | awk '{print $3" "$4}') - T2=$(grep -m1 "Time.Alignment" $FOLDER2/$PREFIX.log | awk '{print $3" "$4}') - M1=$(grep -m1 "Maximum resident set size" $FOLDER1/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') - M2=$(grep -m1 "Maximum resident set size" $FOLDER2/$PREFIX.log | tr -d "(:)" | awk '{print $6" "$5}') - echo -e "\tTIME($T1,$T2)\tMEM($M1,$M2)" -done diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh index 2ee4fbaa..eba3b0d7 100755 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.performance.sh @@ -38,4 +38,4 @@ rm $OUTPUT/*.log $OUTPUT/*.alg \time -v ./bin/align_benchmark -a $ALGORITHM -i ../data/sim.l100K.n1.e10.seq -o $OUTPUT/sim.l100K.e10.Wb.alg $BIWFA &> $OUTPUT/sim.l100K.e10.Wb.log # Run the check -./tests/wfa.utest.performance.cmp.sh tests/ tests/wfa.utest.performance.check/ \ No newline at end of file +./tests/wfa.utest.cmp.sh tests/ tests/wfa.utest.performance.check/ --cmp-performance \ No newline at end of file diff --git a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh index 652ca4dd..71ebcee1 100755 --- a/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh +++ b/src/common/wflign/deps/WFA2-lib/tests/wfa.utest.sh @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash # PROJECT: Wavefront Alignments Algorithms (Unitary Tests) # LICENCE: MIT License # AUTHOR(S): Santiago Marco-Sola @@ -6,13 +6,25 @@ # USAGE: ./wfa.utest.sh # Config -BIN="./bin/align_benchmark" -INPUT="./tests/wfa.utest.seq" -OUTPUT="./tests" -LOG="./tests/wfa.utest.log" +PREFIX=$(dirname $0) +INPUT="$PREFIX/wfa.utest.seq" +OUTPUT="$PREFIX" +LOG="$PREFIX/wfa.utest.log" + +CMP_SCORE=$(readlink -f "$PREFIX/../scripts/wfa.alg.cmp.score.sh") +BIN=$(readlink -f "$PREFIX/../build/bin/align_benchmark") +if [ ! -f "$BIN" ] +then + BIN=$(readlink -f "$PREFIX/../bin/align_benchmark") + if [ ! -f "$BIN" ] + then + echo "[Error] Binaries not built. Please run cmake or make" + exit -1 + fi +fi # Clear -rm $OUTPUT/*.alg $OUTPUT/*.log* +rm $OUTPUT/*.alg $OUTPUT/*.log* &> /dev/null # Run tests for opt in "--check=correct","test" \ @@ -23,65 +35,79 @@ for opt in "--check=correct","test" \ do # Config IFS=','; set -- $opt - IFS=' '; MODE="$1"; PREFIX="$2" - echo ">>> Testing '$PREFIX' ($MODE)" + IFS=' '; MODE="$1"; NAME="$2" + echo ">>> Testing '$NAME' ($MODE)" # Testing distance functions - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.indel.alg -a indel-wfa $MODE >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.edit.alg -a edit-wfa $MODE >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.alg -a gap-affine-wfa $MODE >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine2p.alg -a gap-affine2p-wfa $MODE >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.indel.alg -a indel-wfa $MODE >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.edit.alg -a edit-wfa $MODE >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.alg -a gap-affine-wfa $MODE >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine2p.alg -a gap-affine2p-wfa $MODE >> $LOG 2>&1 # Testing penalty-scores - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.p0.alg -a gap-affine-wfa $MODE --affine-penalties="0,1,2,1" >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.p1.alg -a gap-affine-wfa $MODE --affine-penalties="0,3,1,4" >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.p2.alg -a gap-affine-wfa $MODE --affine-penalties="0,5,3,2" >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.p0.alg -a gap-affine-wfa $MODE --affine-penalties="0,1,2,1" >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.p1.alg -a gap-affine-wfa $MODE --affine-penalties="0,3,1,4" >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.p2.alg -a gap-affine-wfa $MODE --affine-penalties="0,5,3,2" >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.p3.alg -a gap-affine-wfa $MODE --affine-penalties="-5,1,2,1" >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.p4.alg -a gap-affine-wfa $MODE --affine-penalties="-2,3,1,4" >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.p5.alg -a gap-affine-wfa $MODE --affine-penalties="-3,5,3,2" >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.p3.alg -a gap-affine-wfa $MODE --affine-penalties="-5,1,2,1" >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.p4.alg -a gap-affine-wfa $MODE --affine-penalties="-2,3,1,4" >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.p5.alg -a gap-affine-wfa $MODE --affine-penalties="-3,5,3,2" >> $LOG 2>&1 # Heuristics - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.wfapt0.alg -a gap-affine-wfa $MODE --wfa-heuristic=wfa-adaptive --wfa-heuristic-parameters=10,50,1 >> $LOG 2>&1 - \time -v $BIN -i $INPUT -o $OUTPUT/$PREFIX.affine.wfapt1.alg -a gap-affine-wfa $MODE --wfa-heuristic=wfa-adaptive --wfa-heuristic-parameters=10,50,10 >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.wfapt0.alg -a gap-affine-wfa $MODE --wfa-heuristic=wfa-adaptive --wfa-heuristic-parameters=10,50,1 >> $LOG 2>&1 + \time -v $BIN -i $INPUT -o $OUTPUT/$NAME.affine.wfapt1.alg -a gap-affine-wfa $MODE --wfa-heuristic=wfa-adaptive --wfa-heuristic-parameters=10,50,10 >> $LOG 2>&1 done # Intra-tests -diff tests/wfa.utest.check/test.edit.alg tests/wfa.utest.check/test.pb.edit.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.indel.alg tests/wfa.utest.check/test.pb.indel.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.alg tests/wfa.utest.check/test.pb.affine.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine2p.alg tests/wfa.utest.check/test.pb.affine2p.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.p0.alg tests/wfa.utest.check/test.pb.affine.p0.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.p1.alg tests/wfa.utest.check/test.pb.affine.p1.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.p2.alg tests/wfa.utest.check/test.pb.affine.p2.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.p3.alg tests/wfa.utest.check/test.pb.affine.p3.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.p4.alg tests/wfa.utest.check/test.pb.affine.p4.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.p5.alg tests/wfa.utest.check/test.pb.affine.p5.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.wfapt0.alg tests/wfa.utest.check/test.pb.affine.wfapt0.alg >> $LOG.correct 2>&1 -diff tests/wfa.utest.check/test.affine.wfapt1.alg tests/wfa.utest.check/test.pb.affine.wfapt1.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.edit.alg tests/wfa.utest.check/test.biwfa.edit.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.indel.alg tests/wfa.utest.check/test.biwfa.indel.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.alg tests/wfa.utest.check/test.biwfa.affine.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine2p.alg tests/wfa.utest.check/test.biwfa.affine2p.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.p0.alg tests/wfa.utest.check/test.biwfa.affine.p0.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.p1.alg tests/wfa.utest.check/test.biwfa.affine.p1.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.p2.alg tests/wfa.utest.check/test.biwfa.affine.p2.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.p3.alg tests/wfa.utest.check/test.biwfa.affine.p3.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.p4.alg tests/wfa.utest.check/test.biwfa.affine.p4.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.p5.alg tests/wfa.utest.check/test.biwfa.affine.p5.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.wfapt0.alg tests/wfa.utest.check/test.biwfa.affine.wfapt0.alg >> $LOG.correct 2>&1 -./scripts/wfa.alg.cmp.score.sh tests/wfa.utest.check/test.affine.wfapt1.alg tests/wfa.utest.check/test.biwfa.affine.wfapt1.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.edit.alg $PREFIX/wfa.utest.check/test.pb.edit.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.indel.alg $PREFIX/wfa.utest.check/test.pb.indel.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.alg $PREFIX/wfa.utest.check/test.pb.affine.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine2p.alg $PREFIX/wfa.utest.check/test.pb.affine2p.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.p0.alg $PREFIX/wfa.utest.check/test.pb.affine.p0.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.p1.alg $PREFIX/wfa.utest.check/test.pb.affine.p1.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.p2.alg $PREFIX/wfa.utest.check/test.pb.affine.p2.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.p3.alg $PREFIX/wfa.utest.check/test.pb.affine.p3.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.p4.alg $PREFIX/wfa.utest.check/test.pb.affine.p4.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.p5.alg $PREFIX/wfa.utest.check/test.pb.affine.p5.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.wfapt0.alg $PREFIX/wfa.utest.check/test.pb.affine.wfapt0.alg >> $LOG.correct 2>&1 +diff $PREFIX/wfa.utest.check/test.affine.wfapt1.alg $PREFIX/wfa.utest.check/test.pb.affine.wfapt1.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.edit.alg $PREFIX/wfa.utest.check/test.biwfa.edit.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.indel.alg $PREFIX/wfa.utest.check/test.biwfa.indel.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.alg $PREFIX/wfa.utest.check/test.biwfa.affine.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine2p.alg $PREFIX/wfa.utest.check/test.biwfa.affine2p.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.p0.alg $PREFIX/wfa.utest.check/test.biwfa.affine.p0.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.p1.alg $PREFIX/wfa.utest.check/test.biwfa.affine.p1.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.p2.alg $PREFIX/wfa.utest.check/test.biwfa.affine.p2.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.p3.alg $PREFIX/wfa.utest.check/test.biwfa.affine.p3.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.p4.alg $PREFIX/wfa.utest.check/test.biwfa.affine.p4.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.p5.alg $PREFIX/wfa.utest.check/test.biwfa.affine.p5.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.wfapt0.alg $PREFIX/wfa.utest.check/test.biwfa.affine.wfapt0.alg >> $LOG.correct 2>&1 +$CMP_SCORE $PREFIX/wfa.utest.check/test.affine.wfapt1.alg $PREFIX/wfa.utest.check/test.biwfa.affine.wfapt1.alg >> $LOG.correct 2>&1 -# Summary tests +# Summary tests (*.correct,*.time,*.mem) grep "Alignments.Correct" $LOG >> $LOG.correct grep "Time.Alignment" $LOG | awk '{if ($4 != "ms") print $3" "$4}' | sort -n > $LOG.time grep "Maximum resident set size" $LOG | awk '{print $6}' | sort -n > $LOG.mem -echo -n ">>> Correct: " -tail -n 4 $OUTPUT/wfa.utest.log.time $OUTPUT/wfa.utest.check/wfa.utest.log.time -tail -n 4 $OUTPUT/wfa.utest.log.mem $OUTPUT/wfa.utest.check/wfa.utest.log.mem +# Display performance +echo ">>> Performance Time (s): " +paste <(tail -n 4 $OUTPUT/wfa.utest.check/wfa.utest.log.time) <(tail -n 4 $OUTPUT/wfa.utest.log.time) +echo ">>> Performance Mem (KB): " +paste <(tail -n 4 $OUTPUT/wfa.utest.check/wfa.utest.log.mem) <(tail -n 4 $OUTPUT/wfa.utest.log.mem) + +# Display correct ./tests/wfa.utest.cmp.sh $OUTPUT $OUTPUT/wfa.utest.check -grep "Exit status:" $LOG | sort | uniq -c -grep "Command terminated by signal" $LOG | sort | uniq -c -cat $OUTPUT/wfa.utest.log.correct | awk '{print $5$6}' | sort | uniq -c +STATUS=$? +STATUS_EXIT=$(grep "Exit status:" $LOG | grep -v "Exit status: 0" | sort | uniq -c | tr '\n' ' ') +STATUS_SIGNAL=$(grep "Command terminated by signal" $LOG | sort | uniq -c | tr '\n' ' ') +STATUS_CORRECT=$(cat $OUTPUT/wfa.utest.log.correct | awk '{print $5$6}' | sort | uniq -c | tr '\n' ' ') +echo ">>> Correct: ExitStatus($STATUS_EXIT) Signal($STATUS_SIGNAL) Correct($STATUS_CORRECT)" +if [[ $STATUS -eq 0 && "$STATUS_EXIT"=="" && "$STATUS_SIGNAL"=="" ]] +then + echo -e ">>>\n>>> ALL GOOD!\n>>>" + exit 0 +else + echo -e ">>>\n>>> ERROR\n>>>" + exit -1 +fi diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c index 60334b43..dc1e6324 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark.c @@ -51,6 +51,24 @@ #include "benchmark/benchmark_gap_affine.h" #include "benchmark/benchmark_gap_affine2p.h" +/* + * WFA lambda (custom match function) + */ +typedef struct { + char* pattern; + int pattern_length; + char* text; + int text_length; +} match_function_params_t; +match_function_params_t lambda_params; +// Simplest Extend-matching function (for testing purposes) +int lambda_function(int v,int h,void* arguments) { + // Extract parameters + match_function_params_t* const match_arguments = (match_function_params_t*)arguments; + // Check match + if (v >= match_arguments->pattern_length || h >= match_arguments->text_length) return 0; + return (match_arguments->pattern[v] == match_arguments->text[h]); +} /* * Algorithms */ @@ -116,9 +134,7 @@ void align_pairwise_test() { pattern,strlen(pattern),text,strlen(text)); // CIGAR fprintf(stderr,">> WFA2"); - cigar_print_pretty(stderr, - pattern,strlen(pattern),text,strlen(text), - wf_aligner->cigar,wf_aligner->mm_allocator); + cigar_print_pretty(stderr,wf_aligner->cigar,pattern,strlen(pattern),text,strlen(text)); fprintf(stderr,"SCORE: %d \n",cigar_score_gap_affine( wf_aligner->cigar,&affine_penalties)); // Plot @@ -203,15 +219,11 @@ wavefront_aligner_t* align_input_configure_wavefront( // Select alignment form attributes.alignment_form.span = (parameters.endsfree) ? alignment_endsfree : alignment_end2end; // Misc - if (parameters.wfa_match_funct_arguments != NULL) { - attributes.match_funct = parameters.wfa_match_funct; - attributes.match_funct_arguments = parameters.wfa_match_funct_arguments; - } attributes.plot.enabled = (parameters.plot != 0); attributes.plot.align_level = (parameters.plot < 0) ? -1 : parameters.plot - 1; attributes.system.verbose = parameters.verbose; attributes.system.max_memory_abort = parameters.wfa_max_memory; - attributes.system.max_alignment_score = parameters.wfa_max_score; + attributes.system.max_alignment_steps = parameters.wfa_max_steps; attributes.system.max_num_threads = parameters.wfa_max_threads; // Allocate return wavefront_aligner_new(&attributes); @@ -233,6 +245,10 @@ void align_input_configure_global( align_input->mm_allocator = mm_allocator_new(BUFFER_SIZE_1M); // WFA if (align_benchmark_is_wavefront(parameters.algorithm)) { + if (parameters.wfa_lambda) { + align_input->wfa_match_funct = lambda_function; + align_input->wfa_match_funct_arguments = &lambda_params; + } align_input->wf_aligner = align_input_configure_wavefront(align_input); } else { align_input->wf_aligner = NULL; @@ -269,11 +285,11 @@ void align_input_configure_local( } } // Custom extend-match function - if (parameters.wfa_match_funct != NULL) { - match_function_params.pattern = align_input->pattern; - match_function_params.pattern_length = align_input->pattern_length; - match_function_params.text = align_input->text; - match_function_params.text_length = align_input->text_length; + if (parameters.wfa_lambda) { + lambda_params.pattern = align_input->pattern; + lambda_params.pattern_length = align_input->pattern_length; + lambda_params.text = align_input->text; + lambda_params.text_length = align_input->text_length; } } void align_benchmark_free( @@ -306,7 +322,9 @@ bool align_benchmark_read_input( align_input->pattern[align_input->pattern_length] = '\0'; align_input->text = *line2 + 1; align_input->text_length = line2_length - 2; - align_input->text[align_input->text_length] = '\0'; + if (align_input->text[align_input->text_length] == '\n') { + align_input->text[align_input->text_length] = '\0'; + } return true; } /* @@ -458,7 +476,8 @@ void align_benchmark_sequential() { // mm_allocator_print(stderr,align_input.wf_aligner->mm_allocator,false); // mm_allocator_print(stderr,align_input.wf_aligner->bialigner->alg_forward->mm_allocator,false); // mm_allocator_print(stderr,align_input.wf_aligner->bialigner->alg_reverse->mm_allocator,false); - // mm_allocator_print(stderr,align_input.wf_aligner->bialigner->alg_subsidiary->mm_allocator,false); + // mm_allocator_print(stderr,align_input.wf_aligner->bialigner->wf_forward_base->mm_allocator,false); + // mm_allocator_print(stderr,align_input.wf_aligner->bialigner->wf_reverse_base->mm_allocator,false); // Plot if (parameters.plot != 0) align_benchmark_plot_wf(&align_input,seqs_processed); } diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c index f6c72790..e81e351c 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.c @@ -30,10 +30,6 @@ #include "align_benchmark_params.h" -/* - * Match function - */ -match_function_params_t match_function_params; /* * Default parameters */ @@ -84,11 +80,10 @@ align_bench_params_t parameters = { .wfa_heuristic_p2 = -1, .wfa_heuristic_p3 = -1, .wfa_memory_mode = wavefront_memory_high, - .wfa_match_funct = NULL, - .wfa_match_funct_arguments = NULL, .wfa_max_memory = UINT64_MAX, - .wfa_max_score = INT_MAX, + .wfa_max_steps = INT_MAX, .wfa_max_threads = 1, + .wfa_lambda = false, // Other algorithms parameters .bandwidth = -1, // Misc @@ -105,16 +100,6 @@ align_bench_params_t parameters = { .progress = 100000, .verbose = 0, }; -/* - * Simplest Extend-matching function (for testing purposes) - */ -int match_function(int v,int h,void* arguments) { - // Extract parameters - match_function_params_t* match_arguments = (match_function_params_t*)arguments; - // Check match - if (v > match_arguments->pattern_length || h > match_arguments->text_length) return 0; - return (match_arguments->pattern[v] == match_arguments->text[h]); -} /* * Menu */ @@ -173,7 +158,7 @@ void usage() { " P1 = z-drop \n" " P2 = steps-between-cutoffs \n" " --wfa-max-memory BYTES \n" - " --wfa-max-score INT \n" + " --wfa-max-steps INT \n" " --wfa-max-threads INT (intra-parallelism; default=1) \n" " [Other Parameters] \n" " --bandwidth INT \n" @@ -212,10 +197,10 @@ void parse_arguments( { "wfa-memory-mode", required_argument, 0, 1001 }, { "wfa-heuristic", required_argument, 0, 1002 }, { "wfa-heuristic-parameters", required_argument, 0, 1003 }, - { "wfa-custom-match-funct", no_argument, 0, 1004 }, { "wfa-max-memory", required_argument, 0, 1005 }, - { "wfa-max-score", required_argument, 0, 1006 }, + { "wfa-max-steps", required_argument, 0, 1006 }, { "wfa-max-threads", required_argument, 0, 1007 }, + { "wfa-lambda", no_argument, 0, 1008 }, /* Other alignment parameters */ { "bandwidth", required_argument, 0, 2000 }, /* Misc */ @@ -401,19 +386,18 @@ void parse_arguments( } break; } - case 1004: // --wfa-custom-match-funct - parameters.wfa_match_funct = match_function; - parameters.wfa_match_funct_arguments = &match_function_params; - break; case 1005: // --wfa-max-memory parameters.wfa_max_memory = atol(optarg); break; - case 1006: // --wfa-max-score - parameters.wfa_max_score = atoi(optarg); + case 1006: // --wfa-max-steps + parameters.wfa_max_steps = atoi(optarg); break; case 1007: // --wfa-max-threads parameters.wfa_max_threads = atoi(optarg); break; + case 1008: // --wfa-lambda + parameters.wfa_lambda = true; + break; /* * Other alignment parameters */ diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h index 889f16e0..1a0b14cf 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/align_benchmark_params.h @@ -60,17 +60,6 @@ typedef enum { alignment_gap_affine2p_wavefront, } alignment_algorithm_type; -/* - * Match function - */ -typedef struct { - char* pattern; - int pattern_length; - char* text; - int text_length; -} match_function_params_t; -extern match_function_params_t match_function_params; - /* * Align-benchmark Parameters */ @@ -105,11 +94,10 @@ typedef struct { int wfa_heuristic_p2; int wfa_heuristic_p3; wavefront_memory_t wfa_memory_mode; - alignment_match_funct_t wfa_match_funct; - void* wfa_match_funct_arguments; uint64_t wfa_max_memory; - int wfa_max_score; + int wfa_max_steps; int wfa_max_threads; + bool wfa_lambda; // Other algorithms parameters int bandwidth; // Misc diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_check.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_check.c index 8022760a..f748ae0d 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_check.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_check.c @@ -133,8 +133,7 @@ void benchmark_check_alignment_indel( &score_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); indel_dp_compute(&score_matrix, align_input->pattern,align_input->pattern_length, align_input->text,align_input->text_length,cigar); @@ -156,8 +155,7 @@ void benchmark_check_alignment_edit( &score_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); if (align_input->check_bandwidth <= 0) { edit_dp_align(&score_matrix, align_input->pattern,align_input->pattern_length, @@ -187,8 +185,7 @@ void benchmark_check_alignment_gap_linear( &score_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); nw_align(&score_matrix, align_input->check_linear_penalties, align_input->pattern,align_input->pattern_length, @@ -214,8 +211,7 @@ void benchmark_check_alignment_gap_affine( &affine_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Compute correct if (align_input->check_bandwidth <= 0) { swg_align(&affine_matrix,align_input->check_affine_penalties, @@ -248,8 +244,7 @@ void benchmark_check_alignment_gap_affine2p( &affine_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Compute correct affine2p_dp_align( &affine_matrix,align_input->check_affine2p_penalties, diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c index 2e368e1f..2e126701 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_edit.c @@ -78,8 +78,7 @@ void benchmark_edit_dp( &score_matrix,pattern_length+1, text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - pattern_length+text_length, - align_input->mm_allocator); + pattern_length+text_length); // Align timer_start(&align_input->timer); edit_dp_align(&score_matrix, @@ -110,8 +109,7 @@ void benchmark_edit_dp_banded( &score_matrix,pattern_length+1, text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - pattern_length+text_length, - align_input->mm_allocator); + pattern_length+text_length); // Align timer_start(&align_input->timer); edit_dp_align_banded(&score_matrix, @@ -137,9 +135,15 @@ void benchmark_edit_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); + if (align_input->wfa_match_funct == NULL) { + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); + } else { + wavefront_align_lambda(wf_aligner, + align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, + align_input->pattern_length,align_input->text_length); + } timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c index 5492d1d0..3a35f778 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine.c @@ -47,8 +47,7 @@ void benchmark_gap_affine_swg( &affine_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Align timer_start(&align_input->timer); swg_align(&affine_matrix,penalties, @@ -76,8 +75,7 @@ void benchmark_gap_affine_swg_endsfree( &affine_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Align timer_start(&align_input->timer); swg_align_endsfree(&affine_matrix,penalties, @@ -108,8 +106,7 @@ void benchmark_gap_affine_swg_banded( &affine_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Align timer_start(&align_input->timer); swg_align_banded(&affine_matrix,penalties, @@ -135,9 +132,15 @@ void benchmark_gap_affine_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); + if (align_input->wfa_match_funct == NULL) { + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); + } else { + wavefront_align_lambda(wf_aligner, + align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, + align_input->pattern_length,align_input->text_length); + } timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c index a8305d37..3cad6e4c 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_affine2p.c @@ -47,8 +47,7 @@ void benchmark_gap_affine2p_dp( &matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Align timer_start(&align_input->timer); affine2p_dp_align(&matrix,penalties, @@ -74,9 +73,15 @@ void benchmark_gap_affine2p_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); + if (align_input->wfa_match_funct == NULL) { + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); + } else { + wavefront_align_lambda(wf_aligner, + align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, + align_input->pattern_length,align_input->text_length); + } timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c index 45cd2392..f71d799e 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_gap_linear.c @@ -46,8 +46,7 @@ void benchmark_gap_linear_nw( &score_matrix,align_input->pattern_length+1, align_input->text_length+1,align_input->mm_allocator); cigar_t* const cigar = cigar_new( - align_input->pattern_length+align_input->text_length, - align_input->mm_allocator); + align_input->pattern_length+align_input->text_length); // Align timer_start(&align_input->timer); nw_align(&score_matrix,penalties, @@ -73,9 +72,15 @@ void benchmark_gap_linear_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); + if (align_input->wfa_match_funct == NULL) { + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); + } else { + wavefront_align_lambda(wf_aligner, + align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, + align_input->pattern_length,align_input->text_length); + } timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c index 04d73fde..44522db6 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_indel.c @@ -42,9 +42,15 @@ void benchmark_indel_wavefront( wavefront_aligner_t* const wf_aligner = align_input->wf_aligner; // Align timer_start(&align_input->timer); - wavefront_align(wf_aligner, - align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length); + if (align_input->wfa_match_funct == NULL) { + wavefront_align(wf_aligner, + align_input->pattern,align_input->pattern_length, + align_input->text,align_input->text_length); + } else { + wavefront_align_lambda(wf_aligner, + align_input->wfa_match_funct,align_input->wfa_match_funct_arguments, + align_input->pattern_length,align_input->text_length); + } timer_stop(&align_input->timer); // DEBUG if (align_input->debug_flags) { diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c index ccbd915e..20ede464 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.c @@ -47,6 +47,8 @@ void benchmark_align_input_clear( align_input->text_begin_free = 0; align_input->pattern_end_free = 0; align_input->text_end_free = 0; + align_input->wfa_match_funct = NULL; + align_input->wfa_match_funct_arguments = NULL; // Output align_input->output_file = NULL; align_input->output_full = false; @@ -84,10 +86,9 @@ void benchmark_print_alignment( fprintf(stream,"\n"); } if (cigar_computed != NULL) { - cigar_print_pretty(stream, + cigar_print_pretty(stream,cigar_computed, align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length, - cigar_computed,align_input->mm_allocator); + align_input->text,align_input->text_length); } if (cigar_correct != NULL && score_correct != -1) { fprintf(stream," CORRECT \tscore=%d\t",score_correct); @@ -95,10 +96,9 @@ void benchmark_print_alignment( fprintf(stream,"\n"); } if (cigar_correct != NULL) { - cigar_print_pretty(stream, + cigar_print_pretty(stream,cigar_correct, align_input->pattern,align_input->pattern_length, - align_input->text,align_input->text_length, - cigar_correct,align_input->mm_allocator); + align_input->text,align_input->text_length); } } void benchmark_print_output_lite( @@ -151,7 +151,7 @@ void benchmark_print_output( int score = -1; if (score_only) { score = cigar->score; - } else { + } else if (cigar->begin_offset < cigar->end_offset) { switch (distance_metric) { case indel: case edit: @@ -189,14 +189,22 @@ void benchmark_print_stats( fprintf(stream,"[Accuracy]\n"); fprintf(stream," => Alignments.Correct "); counter_print(stream,&align_input->align_correct,&align_input->align,"alg ",true); - fprintf(stream," => Score.Correct "); - counter_print(stream,&align_input->align_score,&align_input->align,"alg ",true); - fprintf(stream," => Score.Total "); - counter_print(stream,&align_input->align_score_total,NULL,"score uds.",true); - fprintf(stream," => Score.Diff "); - counter_print(stream,&align_input->align_score_diff,&align_input->align_score_total,"score uds.",true); - fprintf(stream," => CIGAR.Correct "); - counter_print(stream,&align_input->align_cigar,&align_input->align,"alg ",true); + // Score check + if (align_input->debug_flags & ALIGN_DEBUG_CHECK_SCORE) { + fprintf(stream," => Score.Correct "); + counter_print(stream,&align_input->align_score,&align_input->align,"alg ",true); + fprintf(stream," => Score.Total "); + counter_print(stream,&align_input->align_score_total,NULL,"score uds.",true); + fprintf(stream," => Score.Diff "); + counter_print(stream,&align_input->align_score_diff,&align_input->align_score_total,"score uds.",true); + } + // Alignment check + if (align_input->debug_flags & ALIGN_DEBUG_CHECK_ALIGNMENT) { + fprintf(stream," => CIGAR.Correct "); + counter_print(stream,&align_input->align_cigar,&align_input->align,"alg ",true); + } + // CIGAR stats + fprintf(stream," => CIGAR.Breakdown \n"); fprintf(stream," => CIGAR.Matches "); counter_print(stream,&align_input->align_matches,&align_input->align_bases,"bases ",true); fprintf(stream," => CIGAR.Mismatches "); diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h index b501d057..2d04c4b3 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/benchmark/benchmark_utils.h @@ -62,6 +62,8 @@ typedef struct { int pattern_length; char* text; int text_length; + alignment_match_funct_t wfa_match_funct; + void* wfa_match_funct_arguments; // Penalties linear_penalties_t linear_penalties; affine_penalties_t affine_penalties; diff --git a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/edit/edit_bpm.c b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/edit/edit_bpm.c index 194ce3c6..9254eddf 100644 --- a/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/edit/edit_bpm.c +++ b/src/common/wflign/deps/WFA2-lib/tools/align_benchmark/edit/edit_bpm.c @@ -155,7 +155,7 @@ void edit_bpm_matrix_allocate( bpm_matrix->Mv = Mv; bpm_matrix->Pv = Pv; // CIGAR - bpm_matrix->cigar = cigar_new(pattern_length+text_length,mm_allocator); + bpm_matrix->cigar = cigar_new(pattern_length+text_length); } void edit_bpm_matrix_free( bpm_matrix_t* const bpm_matrix, diff --git a/src/common/wflign/deps/WFA2-lib/utils/Makefile b/src/common/wflign/deps/WFA2-lib/utils/Makefile index 79d36bf0..01665c2e 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/Makefile +++ b/src/common/wflign/deps/WFA2-lib/utils/Makefile @@ -12,7 +12,6 @@ MODULES=bitmap \ dna_text \ heatmap \ sequence_buffer \ - string_padded \ vector SRCS=$(addsuffix .c, $(MODULES)) diff --git a/src/common/wflign/deps/WFA2-lib/utils/commons.h b/src/common/wflign/deps/WFA2-lib/utils/commons.h index 7d602434..92a0b5ef 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/commons.h +++ b/src/common/wflign/deps/WFA2-lib/utils/commons.h @@ -37,7 +37,6 @@ #include #include -#include #include #include #include diff --git a/src/common/wflign/deps/WFA2-lib/utils/heatmap.h b/src/common/wflign/deps/WFA2-lib/utils/heatmap.h index 9def0ed5..fddadd16 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/heatmap.h +++ b/src/common/wflign/deps/WFA2-lib/utils/heatmap.h @@ -31,6 +31,8 @@ #ifndef HEATMAP_H_ #define HEATMAP_H_ +#include + /* * Heatmap */ diff --git a/src/common/wflign/deps/WFA2-lib/utils/string_padded.c b/src/common/wflign/deps/WFA2-lib/utils/string_padded.c deleted file mode 100644 index 99c10062..00000000 --- a/src/common/wflign/deps/WFA2-lib/utils/string_padded.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * The MIT License - * - * Wavefront Alignment Algorithms - * Copyright (c) 2017 by Santiago Marco-Sola - * - * This file is part of Wavefront Alignment Algorithms. - * - * 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. - * - * PROJECT: Wavefront Alignment Algorithms - * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: Padded string module to avoid handling corner conditions - */ - -#include "utils/commons.h" -#include "system/mm_allocator.h" -#include "utils/string_padded.h" - -/* - * Strings (text/pattern) padded - */ -void strings_padded_add_padding( - const char* const buffer, - const int buffer_length, - const int begin_padding_length, - const int end_padding_length, - const char padding_value, - char** const buffer_padded, - char** const buffer_padded_begin, - const bool reverse_sequence, - mm_allocator_t* const mm_allocator) { - // Allocate - const int buffer_padded_length = begin_padding_length + buffer_length + end_padding_length; - *buffer_padded = mm_allocator_malloc(mm_allocator,buffer_padded_length); - // Add begin padding - memset(*buffer_padded,padding_value,begin_padding_length); - // Copy buffer - *buffer_padded_begin = *buffer_padded + begin_padding_length; - if (reverse_sequence) { - int i; - for (i=0;imm_allocator = mm_allocator; - // Compute padding dimensions - const int pattern_begin_padding_length = 0; - const int pattern_end_padding_length = padding_length; - const int text_begin_padding_length = 0; - const int text_end_padding_length = padding_length; - // Add padding - strings_padded_add_padding( - pattern,pattern_length, - pattern_begin_padding_length,pattern_end_padding_length,'?', - &(strings_padded->pattern_padded_buffer), - &(strings_padded->pattern_padded), - reverse_sequences,mm_allocator); - strings_padded_add_padding( - text,text_length, - text_begin_padding_length,text_end_padding_length,'!', - &(strings_padded->text_padded_buffer), - &(strings_padded->text_padded), - reverse_sequences,mm_allocator); - // Return - return strings_padded; -} -strings_padded_t* strings_padded_new_rhomb( - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const int padding_length, - const bool reverse_sequences, - mm_allocator_t* const mm_allocator) { - // Allocate - strings_padded_t* const strings_padded = - mm_allocator_alloc(mm_allocator,strings_padded_t); - strings_padded->mm_allocator = mm_allocator; - // Compute padding dimensions - const int pattern_begin_padding_length = text_length + padding_length; - const int pattern_end_padding_length = pattern_length + text_length + padding_length; - const int text_begin_padding_length = padding_length; - const int text_end_padding_length = text_length + padding_length; - // Add padding - strings_padded_add_padding( - pattern,pattern_length, - pattern_begin_padding_length,pattern_end_padding_length,'?', - &(strings_padded->pattern_padded_buffer), - &(strings_padded->pattern_padded), - reverse_sequences,mm_allocator); - strings_padded_add_padding( - text,text_length, - text_begin_padding_length,text_end_padding_length,'!', - &(strings_padded->text_padded_buffer), - &(strings_padded->text_padded), - reverse_sequences,mm_allocator); - // Set lengths - strings_padded->pattern_length = pattern_length; - strings_padded->text_length = text_length; - // Return - return strings_padded; -} -void strings_padded_delete(strings_padded_t* const strings_padded) { - mm_allocator_free(strings_padded->mm_allocator,strings_padded->pattern_padded_buffer); - mm_allocator_free(strings_padded->mm_allocator,strings_padded->text_padded_buffer); - mm_allocator_free(strings_padded->mm_allocator,strings_padded); -} diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/Makefile b/src/common/wflign/deps/WFA2-lib/wavefront/Makefile index c30efdde..1b372eeb 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/Makefile +++ b/src/common/wflign/deps/WFA2-lib/wavefront/Makefile @@ -24,11 +24,15 @@ MODULES=wavefront_align \ wavefront_debug \ wavefront_display \ wavefront_extend \ + wavefront_extend_kernels_avx \ + wavefront_extend_kernels \ wavefront_heuristic \ wavefront_pcigar \ wavefront_penalties \ + wavefront_sequences \ wavefront_plot \ wavefront_slab \ + wavefront_termination \ wavefront_unialign \ wavefront diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c index 8705d3af..41b49b6b 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.c @@ -45,11 +45,25 @@ /* * Checks */ -void wavefront_align_checks( +void wavefront_align_presets__checks( wavefront_aligner_t* const wf_aligner, const int pattern_length, const int text_length) { + // Parameters alignment_form_t* const form = &wf_aligner->alignment_form; + /* + * Configuration presets + */ + if (form->span == alignment_endsfree && wf_aligner->alignment_form.extension) { + // Configure WF-extend mode + form->pattern_begin_free = 0; + form->pattern_end_free = pattern_length; + form->text_begin_free = 0; + form->text_end_free = text_length; + } + /* + * Checks + */ if (wf_aligner->bialigner != NULL) { const bool ends_free = form->pattern_begin_free > 0 || @@ -57,7 +71,11 @@ void wavefront_align_checks( form->text_begin_free > 0 || form->text_end_free > 0; if (ends_free) { - fprintf(stderr,"[WFA] BiWFA and ends-free is not supported yet\n"); + fprintf(stderr,"[WFA] BiWFA ends-free has not been tested properly yet (let me know and I'll do it)\n"); + exit(1); + } + if (wf_aligner->alignment_form.extension) { + fprintf(stderr,"[WFA] BiWFA extension is not implemented yet (let me know and I'll add it)\n"); exit(1); } } @@ -108,49 +126,89 @@ void wavefront_align_unidirectional_cleanup( } } void wavefront_align_unidirectional( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length) { - // Prepare alignment - wavefront_unialign_init( - wf_aligner,pattern,pattern_length,text,text_length, - affine2p_matrix_M,affine2p_matrix_M); - // DEBUG - wavefront_debug_prologue(wf_aligner,pattern,pattern_length,text,text_length); + wavefront_aligner_t* const wf_aligner) { // Wavefront align sequences - wavefront_unialign(wf_aligner); + wavefront_unialign_init(wf_aligner,affine2p_matrix_M,affine2p_matrix_M); // Init + wavefront_unialign(wf_aligner); // Align // Finish - if (wf_aligner->align_status.status == WF_STATUS_MAX_SCORE_REACHED) return; // Alignment paused + if (wf_aligner->align_status.status == WF_STATUS_MAX_STEPS_REACHED) return; // Alignment paused wavefront_align_unidirectional_cleanup(wf_aligner); - // DEBUG - wavefront_debug_epilogue(wf_aligner); - wavefront_debug_check_correct(wf_aligner); } /* * Wavefront Alignment Bidirectional */ void wavefront_align_bidirectional( + wavefront_aligner_t* const wf_aligner) { + // Bidirectional alignment + wavefront_bialign(wf_aligner); // Align + // Finish + wf_aligner->align_status.memory_used = wavefront_aligner_get_size(wf_aligner); +} +/* + * Wavefront Alignment Dispatcher + */ +int wavefront_align_lambda( wavefront_aligner_t* const wf_aligner, - const char* const pattern, + alignment_match_funct_t match_funct, + void* match_funct_arguments, const int pattern_length, - const char* const text, const int text_length) { + // Checks + wavefront_align_presets__checks(wf_aligner,pattern_length,text_length); + wavefront_debug_begin(wf_aligner); + // Plot + if (wf_aligner->plot != NULL) wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); + // Dispatcher + if (wf_aligner->bialigner == NULL) { + // Prepare Sequences + wavefront_sequences_init_lambda(&wf_aligner->sequences, + match_funct,match_funct_arguments, + pattern_length,text_length,false); + wavefront_align_unidirectional(wf_aligner); + } else { + // Prepare Sequences + wavefront_bialigner_set_sequences_lambda(wf_aligner->bialigner, + match_funct,match_funct_arguments, + pattern_length,text_length); + // Align + wavefront_align_bidirectional(wf_aligner); + } // DEBUG - wavefront_debug_prologue(wf_aligner,pattern,pattern_length,text,text_length); - // Bidirectional alignment - wavefront_bialign(wf_aligner,pattern,pattern_length,text,text_length); - // Finish - const uint64_t memory_used = wavefront_aligner_get_size(wf_aligner); - wf_aligner->align_status.memory_used = memory_used; + wavefront_debug_end(wf_aligner); + wavefront_debug_check_correct(wf_aligner); + // Return + return wf_aligner->align_status.status; +} +int wavefront_align_packed2bits( + wavefront_aligner_t* const wf_aligner, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length) { + // Checks + wavefront_align_presets__checks(wf_aligner,pattern_length,text_length); + wavefront_debug_begin(wf_aligner); + // Plot + if (wf_aligner->plot != NULL) wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); + // Dispatcher + if (wf_aligner->bialigner == NULL) { + // Prepare Sequences + wavefront_sequences_init_packed2bits(&wf_aligner->sequences, + pattern,pattern_length,text,text_length,false); + wavefront_align_unidirectional(wf_aligner); + } else { + // Prepare Sequences + wavefront_bialigner_set_sequences_packed2bits(wf_aligner->bialigner, + pattern,pattern_length,text,text_length); + // Align + wavefront_align_bidirectional(wf_aligner); + } // DEBUG - wavefront_debug_epilogue(wf_aligner); + wavefront_debug_end(wf_aligner); wavefront_debug_check_correct(wf_aligner); + // Return + return wf_aligner->align_status.status; } -/* - * Wavefront Alignment Dispatcher - */ int wavefront_align( wavefront_aligner_t* const wf_aligner, const char* const pattern, @@ -158,26 +216,38 @@ int wavefront_align( const char* const text, const int text_length) { // Checks - wavefront_align_checks(wf_aligner,pattern_length,text_length); + wavefront_align_presets__checks(wf_aligner,pattern_length,text_length); + wavefront_debug_begin(wf_aligner); // Plot - if (wf_aligner->plot != NULL) { - wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); - } + if (wf_aligner->plot != NULL) wavefront_plot_resize(wf_aligner->plot,pattern_length,text_length); // Dispatcher - if (wf_aligner->bialigner != NULL) { - wavefront_align_bidirectional(wf_aligner,pattern,pattern_length,text,text_length); + if (wf_aligner->bialigner == NULL) { + // Prepare Sequences + wavefront_sequences_init_ascii(&wf_aligner->sequences, + pattern,pattern_length,text,text_length,false); + wavefront_align_unidirectional(wf_aligner); } else { - wavefront_align_unidirectional(wf_aligner,pattern,pattern_length,text,text_length); + // Prepare Sequences + wavefront_bialigner_set_sequences_ascii(wf_aligner->bialigner, + pattern,pattern_length,text,text_length); + // Align + wavefront_align_bidirectional(wf_aligner); } + // DEBUG + wavefront_debug_end(wf_aligner); + wavefront_debug_check_correct(wf_aligner); // Return return wf_aligner->align_status.status; } +/* + * Wavefront Alignment Resume (Experimental) + */ int wavefront_align_resume( wavefront_aligner_t* const wf_aligner) { // Parameters wavefront_align_status_t* const align_status = &wf_aligner->align_status; // Check current alignment status - if (align_status->status != WF_STATUS_MAX_SCORE_REACHED || + if (align_status->status != WF_STATUS_MAX_STEPS_REACHED || wf_aligner->bialigner != NULL) { fprintf(stderr,"[WFA] Alignment cannot be resumed\n"); exit(1); @@ -185,12 +255,11 @@ int wavefront_align_resume( // Resume aligning sequences wavefront_unialign(wf_aligner); // Finish alignment - if (align_status->status == WF_STATUS_MAX_SCORE_REACHED) { - return WF_STATUS_MAX_SCORE_REACHED; // Alignment paused + if (align_status->status == WF_STATUS_MAX_STEPS_REACHED) { + return WF_STATUS_MAX_STEPS_REACHED; // Alignment paused } wavefront_align_unidirectional_cleanup(wf_aligner); // DEBUG - wavefront_debug_epilogue(wf_aligner); wavefront_debug_check_correct(wf_aligner); // Return return align_status->status; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h index 71f97230..85180add 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_align.h @@ -42,5 +42,15 @@ int wavefront_align( const int pattern_length, const char* const text, const int text_length); -int wavefront_align_resume( - wavefront_aligner_t* const wf_aligner); +int wavefront_align_lambda( + wavefront_aligner_t* const wf_aligner, + alignment_match_funct_t const match_funct, + void* match_funct_arguments, + const int pattern_length, + const int text_length); +int wavefront_align_packed2bits( + wavefront_aligner_t* const wf_aligner, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c index dadb777a..f32ed268 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.c @@ -34,6 +34,8 @@ #include "wavefront_components.h" #include "wavefront_heuristic.h" #include "wavefront_plot.h" +#include "wavefront_compute.h" +#include "wavefront_sequences.h" /* * Configuration @@ -44,22 +46,82 @@ /* * Error messages */ -char* wf_error_msg[] = -{ - /* WF_STATUS_OOM == -3 */ "[WFA] Alignment failed. Maximum memory threshold reached", - /* WF_STATUS_MAX_SCORE_REACHED == -2 */ "[WFA] Alignment failed. Maximum score reached", - /* WF_STATUS_UNFEASIBLE == -1 */ "[WFA] Alignment unfeasible (possible due to heuristic parameters)", - /* WF_STATUS_SUCCESSFUL == 0 */ "[WFA] Alignment finished successfully", -}; +// OK +#define WF_STATUS_ALG_COMPLETED_MSG "[WFA] Alignment completed successfully" +#define WF_STATUS_ALG_PARTIAL_MSG "[WFA] Alignment extension computed (partial alignment)" +#define WF_STATUS_ALG_COMPLETED_MSG_SHORT "OK.Full" +#define WF_STATUS_ALG_PARTIAL_MSG_SHORT "OK.Partial" +// FAILED +#define WF_STATUS_MAX_STEPS_REACHED_MSG "[WFA] Alignment failed. Maximum WFA-steps limit reached" +#define WF_STATUS_OOM_MSG "[WFA] Alignment failed. Maximum memory limit reached" +#define WF_STATUS_UNATTAINABLE_MSG "[WFA] Alignment failed. Unattainable under configured heuristics" +#define WF_STATUS_MAX_STEPS_REACHED_MSG_SHORT "FAILED.MaxWFASteps" +#define WF_STATUS_OOM_MSG_SHORT "FAILED.OOM" +#define WF_STATUS_UNATTAINABLE_MSG_SHORT "FAILED.Unattainable" + +// Internal +#define WF_STATUS_END_REACHED_MSG "[WFA] Alignment end reached" +#define WF_STATUS_END_UNREACHABLE_MSG "[WFA] Alignment end unreachable under current configuration (due to heuristics like Z-drop)" +#define WF_STATUS_UNKNOWN_MSG "[WFA] Unknown error code" +#define WF_STATUS_END_REACHED_MSG_SHORT "INTERNAL.Reached" +#define WF_STATUS_END_UNREACHABLE_MSG_SHORT "INTERNAL.Dropped" +#define WF_STATUS_UNKNOWN_MSG_SHORT "Unknown" +/* */ char* wavefront_align_strerror(const int error_code) { - if (error_code > 0) { - fprintf(stderr,"[WFA] Internal alignment error code (%d)",error_code); - exit(1); + // OK + if (error_code == WF_STATUS_ALG_COMPLETED) return WF_STATUS_ALG_COMPLETED_MSG; + if (error_code == WF_STATUS_ALG_PARTIAL) return WF_STATUS_ALG_PARTIAL_MSG; + // FAILED + if (error_code == WF_STATUS_MAX_STEPS_REACHED) return WF_STATUS_MAX_STEPS_REACHED_MSG; + if (error_code == WF_STATUS_OOM) return WF_STATUS_OOM_MSG; + if (error_code == WF_STATUS_UNATTAINABLE) return WF_STATUS_UNATTAINABLE_MSG; + // Internal + if (error_code == WF_STATUS_END_REACHED) return WF_STATUS_END_REACHED_MSG; + if (error_code == WF_STATUS_END_UNREACHABLE) return WF_STATUS_END_UNREACHABLE_MSG; + // Unknown + return WF_STATUS_UNKNOWN_MSG; +} +char* wavefront_align_strerror_short(const int error_code) { + // OK + if (error_code == WF_STATUS_ALG_COMPLETED) return WF_STATUS_ALG_COMPLETED_MSG_SHORT; + if (error_code == WF_STATUS_ALG_PARTIAL) return WF_STATUS_ALG_PARTIAL_MSG_SHORT; + // FAILED + if (error_code == WF_STATUS_MAX_STEPS_REACHED) return WF_STATUS_MAX_STEPS_REACHED_MSG_SHORT; + if (error_code == WF_STATUS_OOM) return WF_STATUS_OOM_MSG_SHORT; + if (error_code == WF_STATUS_UNATTAINABLE) return WF_STATUS_UNATTAINABLE_MSG_SHORT; + // Internal + if (error_code == WF_STATUS_END_REACHED) return WF_STATUS_END_REACHED_MSG_SHORT; + if (error_code == WF_STATUS_END_UNREACHABLE) return WF_STATUS_END_UNREACHABLE_MSG_SHORT; + // Unknown + return WF_STATUS_UNKNOWN_MSG_SHORT; +} +/* + * Initialize Status & System + */ +void wavefront_aligner_init_status( + wavefront_aligner_t* const wf_aligner) { + wf_aligner->align_status.status = WF_STATUS_OK; + wf_aligner->align_status.score = 0; + wf_aligner->align_status.dropped = false; +} +void wavefront_aligner_init_system( + wavefront_aligner_t* const wf_aligner) { + // Reset effective limits + wf_aligner->system.max_memory_compact = BUFFER_SIZE_256M; + wf_aligner->system.max_memory_resident = BUFFER_SIZE_256M + BUFFER_SIZE_256M; + switch (wf_aligner->memory_mode) { + case wavefront_memory_med: + wf_aligner->system.max_partial_compacts = 4; + break; + case wavefront_memory_low: + wf_aligner->system.max_partial_compacts = 1; + break; + default: + break; } - return wf_error_msg[error_code+3]; } /* - * Setup + * Initialize Memory */ wavefront_aligner_t* wavefront_aligner_init_mm( mm_allocator_t* mm_allocator, @@ -90,6 +152,9 @@ wavefront_aligner_t* wavefront_aligner_init_mm( // Return return wf_aligner; } +/* + * Initialize Penalties + */ void wavefront_aligner_init_penalties( wavefront_aligner_t* const wf_aligner, wavefront_aligner_attr_t* const attributes) { @@ -117,6 +182,9 @@ void wavefront_aligner_init_penalties( break; } } +/* + * Initialize Heuristics + */ void wavefront_aligner_init_heuristic( wavefront_aligner_t* const wf_aligner, wavefront_aligner_attr_t* const attributes) { @@ -156,6 +224,9 @@ void wavefront_aligner_init_heuristic( } } } +/* + * Initialize Alignment (mode, scope, form) + */ void wavefront_aligner_init_alignment( wavefront_aligner_t* const wf_aligner, wavefront_aligner_attr_t* const attributes, @@ -173,10 +244,180 @@ void wavefront_aligner_init_alignment( // Memory mode wf_aligner->memory_mode = attributes->memory_mode; wavefront_aligner_init_heuristic(wf_aligner,attributes); - // Custom matching functions - wf_aligner->match_funct = attributes->match_funct; - wf_aligner->match_funct_arguments = attributes->match_funct_arguments; } +/* + * Initialize wavefront-vectors (Initial alignment conditions) + */ +void wavefront_aligner_init_wf_m( + wavefront_aligner_t* const wf_aligner) { + // Parameters + wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; + wavefront_components_t* const wf_components = &wf_aligner->wf_components; + const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; + wavefront_penalties_t* const penalties = &wf_aligner->penalties; + alignment_form_t* const form = &wf_aligner->alignment_form; + // Consider ends-free + const int hi = (penalties->match==0) ? form->text_begin_free : 0; + const int lo = (penalties->match==0) ? -form->pattern_begin_free : 0; + // Compute dimensions + int effective_lo, effective_hi; + wavefront_compute_limits_output(wf_aligner,lo,hi,&effective_lo,&effective_hi); + // Initialize end2end (wavefront zero) + wf_components->mwavefronts[0] = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); + wf_components->mwavefronts[0]->offsets[0] = 0; + wf_components->mwavefronts[0]->lo = lo; + wf_components->mwavefronts[0]->hi = hi; + // Store initial BT-piggypack element + if (wf_components->bt_piggyback) { + const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,0); + wf_components->mwavefronts[0]->bt_pcigar[0] = 0; + wf_components->mwavefronts[0]->bt_prev[0] = block_idx; + } + // Initialize ends-free + if (form->span == alignment_endsfree && penalties->match == 0) { + // Text begin-free + const int text_begin_free = form->text_begin_free; + int h; + for (h=1;h<=text_begin_free;++h) { + const int k = DPMATRIX_DIAGONAL(h,0); + wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(h,0); + if (wf_components->bt_piggyback) { + const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,h); + wf_components->mwavefronts[0]->bt_pcigar[k] = 0; + wf_components->mwavefronts[0]->bt_prev[k] = block_idx; + } + } + // Pattern begin-free + const int pattern_begin_free = form->pattern_begin_free; + int v; + for (v=1;v<=pattern_begin_free;++v) { + const int k = DPMATRIX_DIAGONAL(0,v); + wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(0,v); + if (wf_components->bt_piggyback) { + const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,v,0); + wf_components->mwavefronts[0]->bt_pcigar[k] = 0; + wf_components->mwavefronts[0]->bt_prev[k] = block_idx; + } + } + } + // Nullify unused WFs + if (distance_metric <= gap_linear) return; + wf_components->d1wavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + if (distance_metric==gap_affine) return; + wf_components->d2wavefronts[0] = NULL; + wf_components->i2wavefronts[0] = NULL; +} +void wavefront_aligner_init_wf( + wavefront_aligner_t* const wf_aligner) { + // Parameters + wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; + wavefront_components_t* const wf_components = &wf_aligner->wf_components; + const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; + // Init wavefronts + if (wf_aligner->component_begin == affine2p_matrix_M) { + // Initialize + wavefront_aligner_init_wf_m(wf_aligner); + // Nullify unused WFs + if (distance_metric <= gap_linear) return; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = NULL; + if (distance_metric == gap_affine) return; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = NULL; + } else { + // Compute dimensions + int effective_lo, effective_hi; // Effective lo/hi + wavefront_compute_limits_output(wf_aligner,0,0,&effective_lo,&effective_hi); + wavefront_t* const wavefront = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); + // Initialize + switch (wf_aligner->component_begin) { + case affine2p_matrix_I1: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = wavefront; + wf_components->i1wavefronts[0]->offsets[0] = 0; + wf_components->i1wavefronts[0]->lo = 0; + wf_components->i1wavefronts[0]->hi = 0; + wf_components->d1wavefronts[0] = NULL; + // Nullify unused WFs + if (distance_metric==gap_affine) return; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = NULL; + break; + case affine2p_matrix_I2: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = NULL; + wf_components->i2wavefronts[0] = wavefront; + wf_components->i2wavefronts[0]->offsets[0] = 0; + wf_components->i2wavefronts[0]->lo = 0; + wf_components->i2wavefronts[0]->hi = 0; + wf_components->d2wavefronts[0] = NULL; + break; + case affine2p_matrix_D1: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = wavefront; + wf_components->d1wavefronts[0]->offsets[0] = 0; + wf_components->d1wavefronts[0]->lo = 0; + wf_components->d1wavefronts[0]->hi = 0; + // Nullify unused WFs + if (distance_metric==gap_affine) return; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = NULL; + break; + case affine2p_matrix_D2: + wf_components->mwavefronts[0] = NULL; + wf_components->i1wavefronts[0] = NULL; + wf_components->d1wavefronts[0] = NULL; + wf_components->i2wavefronts[0] = NULL; + wf_components->d2wavefronts[0] = wavefront; + wf_components->d2wavefronts[0]->offsets[0] = 0; + wf_components->d2wavefronts[0]->lo = 0; + wf_components->d2wavefronts[0]->hi = 0; + break; + default: + break; + } + } +} +/* + * Initialize Aligner (to perform a new alignment) + */ +void wavefront_aligner_init( + wavefront_aligner_t* const wf_aligner, + const int align_level) { + // Parameters + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; + // Configure status + wavefront_aligner_init_status(wf_aligner); + // Heuristics clear + wavefront_heuristic_clear(&wf_aligner->heuristic); + // Wavefront components + wavefront_components_resize(&wf_aligner->wf_components, + pattern_length,text_length,&wf_aligner->penalties); + // CIGAR + if (wf_aligner->alignment_scope == compute_alignment) { + cigar_resize(wf_aligner->cigar,2*(pattern_length+text_length)); + } + // Slab + wavefront_slab_clear(wf_aligner->wavefront_slab); + // System + wavefront_aligner_init_system(wf_aligner); + // Initialize wavefront + wf_aligner->align_status.num_null_steps = 0; // Zero null steps + wf_aligner->alignment_end_pos.score = -1; // Not aligned + wf_aligner->alignment_end_pos.k = DPMATRIX_DIAGONAL_NULL; + wf_aligner->alignment_end_pos.offset = WAVEFRONT_OFFSET_NULL; + wavefront_aligner_init_wf(wf_aligner); + // Plot (WF_0) + if (wf_aligner->plot != NULL) wavefront_plot(wf_aligner,0,align_level); +} +/* + * Setup + */ wavefront_aligner_t* wavefront_aligner_new( wavefront_aligner_attr_t* attributes) { // Parameters @@ -211,10 +452,10 @@ wavefront_aligner_t* wavefront_aligner_new( wf_aligner->mm_allocator); } // Sequences - wf_aligner->sequences = NULL; + wavefront_sequences_allocate(&wf_aligner->sequences); // CIGAR const int cigar_length = (score_only) ? 10 : 2*(PATTERN_LENGTH_INIT+TEXT_LENGTH_INIT); - wf_aligner->cigar = cigar_new(cigar_length,wf_aligner->mm_allocator); + wf_aligner->cigar = cigar_new(cigar_length); // System wf_aligner->system = attributes->system; // Return @@ -222,11 +463,6 @@ wavefront_aligner_t* wavefront_aligner_new( } void wavefront_aligner_reap( wavefront_aligner_t* const wf_aligner) { - // Padded sequences - if (wf_aligner->sequences != NULL) { - strings_padded_delete(wf_aligner->sequences); - wf_aligner->sequences = NULL; - } // Select alignment mode if (wf_aligner->bialigner != NULL) { wavefront_bialigner_reap(wf_aligner->bialigner); @@ -242,10 +478,8 @@ void wavefront_aligner_delete( // Parameters mm_allocator_t* const mm_allocator = wf_aligner->mm_allocator; const bool mm_allocator_own = wf_aligner->mm_allocator_own; - // Padded sequences - if (wf_aligner->sequences != NULL) { - strings_padded_delete(wf_aligner->sequences); - } + // Sequences + wavefront_sequences_free(&wf_aligner->sequences); // Select alignment mode if (wf_aligner->bialigner != NULL) { wavefront_bialigner_delete(wf_aligner->bialigner); @@ -264,7 +498,7 @@ void wavefront_aligner_delete( // MM mm_allocator_free(mm_allocator,wf_aligner); if (mm_allocator_own) { - mm_allocator_delete(wf_aligner->mm_allocator); + mm_allocator_delete(mm_allocator); } } /* @@ -273,6 +507,7 @@ void wavefront_aligner_delete( void wavefront_aligner_set_alignment_end_to_end( wavefront_aligner_t* const wf_aligner) { wf_aligner->alignment_form.span = alignment_end2end; + wf_aligner->alignment_form.extension = false; } void wavefront_aligner_set_alignment_free_ends( wavefront_aligner_t* const wf_aligner, @@ -281,11 +516,17 @@ void wavefront_aligner_set_alignment_free_ends( const int text_begin_free, const int text_end_free) { wf_aligner->alignment_form.span = alignment_endsfree; + wf_aligner->alignment_form.extension = false; wf_aligner->alignment_form.pattern_begin_free = pattern_begin_free; wf_aligner->alignment_form.pattern_end_free = pattern_end_free; wf_aligner->alignment_form.text_begin_free = text_begin_free; wf_aligner->alignment_form.text_end_free = text_end_free; } +void wavefront_aligner_set_alignment_extension( + wavefront_aligner_t* const wf_aligner) { + wf_aligner->alignment_form.span = alignment_endsfree; + wf_aligner->alignment_form.extension = true; +} /* * Heuristic configuration */ @@ -358,30 +599,16 @@ void wavefront_aligner_set_heuristic_zdrop( wavefront_bialigner_set_heuristic(wf_aligner->bialigner,&wf_aligner->heuristic); } } -/* - * Match-funct configuration - */ -void wavefront_aligner_set_match_funct( - wavefront_aligner_t* const wf_aligner, - int (*match_funct)(int,int,void*), - void* const match_funct_arguments) { - wf_aligner->match_funct = match_funct; - wf_aligner->match_funct_arguments = match_funct_arguments; - if (wf_aligner->bialigner != NULL) { - wavefront_bialigner_set_match_funct( - wf_aligner->bialigner,match_funct,match_funct_arguments); - } -} /* * System configuration */ -void wavefront_aligner_set_max_alignment_score( +void wavefront_aligner_set_max_alignment_steps( wavefront_aligner_t* const wf_aligner, - const int max_alignment_score) { - wf_aligner->system.max_alignment_score = max_alignment_score; + const int max_alignment_steps) { + wf_aligner->system.max_alignment_steps = max_alignment_steps; if (wf_aligner->bialigner != NULL) { - wavefront_bialigner_set_max_alignment_score( - wf_aligner->bialigner,max_alignment_score); + wavefront_bialigner_set_max_alignment_steps( + wf_aligner->bialigner,max_alignment_steps); } } void wavefront_aligner_set_max_memory( @@ -396,22 +623,22 @@ void wavefront_aligner_set_max_memory( } } void wavefront_aligner_set_max_num_threads( - wavefront_aligner_t* const wf_aligner, - const int max_num_threads) { - wf_aligner->system.max_num_threads = max_num_threads; - if (wf_aligner->bialigner != NULL) { - wavefront_bialigner_set_max_num_threads( - wf_aligner->bialigner,max_num_threads); - } + wavefront_aligner_t* const wf_aligner, + const int max_num_threads) { + wf_aligner->system.max_num_threads = max_num_threads; + if (wf_aligner->bialigner != NULL) { + wavefront_bialigner_set_max_num_threads( + wf_aligner->bialigner,max_num_threads); + } } void wavefront_aligner_set_min_offsets_per_thread( - wavefront_aligner_t* const wf_aligner, - const int min_offsets_per_thread) { - wf_aligner->system.min_offsets_per_thread = min_offsets_per_thread; - if (wf_aligner->bialigner != NULL) { - wavefront_bialigner_set_min_offsets_per_thread( - wf_aligner->bialigner,min_offsets_per_thread); - } + wavefront_aligner_t* const wf_aligner, + const int min_offsets_per_thread) { + wf_aligner->system.min_offsets_per_thread = min_offsets_per_thread; + if (wf_aligner->bialigner != NULL) { + wavefront_bialigner_set_min_offsets_per_thread( + wf_aligner->bialigner,min_offsets_per_thread); + } } /* * Utils @@ -433,32 +660,44 @@ uint64_t wavefront_aligner_get_size( return sub_aligners + bt_buffer_size + slab_size; } } +bool wavefront_aligner_maxtrim_cigar( + wavefront_aligner_t* const wf_aligner) { + switch (wf_aligner->penalties.distance_metric) { + case gap_linear: + return cigar_maxtrim_gap_linear(wf_aligner->cigar,&wf_aligner->penalties.linear_penalties); + case gap_affine: + return cigar_maxtrim_gap_affine(wf_aligner->cigar,&wf_aligner->penalties.affine_penalties); + case gap_affine_2p: + return cigar_maxtrim_gap_affine2p(wf_aligner->cigar,&wf_aligner->penalties.affine2p_penalties); + default: + return false; // Maxtrim does not apply to edit/indel distances + } +} /* * Display */ -void wavefront_aligner_print_type( +void wavefront_aligner_print_mode( FILE* const stream, wavefront_aligner_t* const wf_aligner) { - if (wf_aligner->align_mode_tag == NULL) { - switch (wf_aligner->align_mode) { - case wf_align_biwfa: - fprintf(stream,"BiWFA"); - break; - case wf_align_biwfa_breakpoint_forward: - fprintf(stream,"BiWFA::Forward"); - break; - case wf_align_biwfa_breakpoint_reverse: - fprintf(stream,"BiWFA::Reverse"); - break; - case wf_align_biwfa_subsidiary: - fprintf(stream,"BiWFA::SubWFA"); - break; - default: - fprintf(stream,"WFA"); - break; - } - } else { - fprintf(stream,"%s",wf_aligner->align_mode_tag); + if (wf_aligner->align_mode_tag != NULL) { + fprintf(stream,"%s::",wf_aligner->align_mode_tag); + } + switch (wf_aligner->align_mode) { + case wf_align_biwfa: + fprintf(stream,"BiWFA"); + break; + case wf_align_biwfa_breakpoint_forward: + fprintf(stream,"BiWFA::Forward"); + break; + case wf_align_biwfa_breakpoint_reverse: + fprintf(stream,"BiWFA::Reverse"); + break; + case wf_align_biwfa_subsidiary: + fprintf(stream,"BiWFA::SubWFA"); + break; + default: + fprintf(stream,"WFA"); + break; } } void wavefront_aligner_print_scope( @@ -477,14 +716,19 @@ void wavefront_aligner_print_scope( wf_aligner->alignment_form.text_end_free); } } -void wavefront_aligner_print_mode( +void wavefront_aligner_print_conf( FILE* const stream, wavefront_aligner_t* const wf_aligner) { - fprintf(stream,"(%s,",(wf_aligner->alignment_scope==compute_score)?"Score":"Alg"); + fprintf(stream,"("); switch (wf_aligner->memory_mode) { - case wavefront_memory_high: fprintf(stream,"MHigh)"); break; - case wavefront_memory_med: fprintf(stream,"MMed)"); break; - case wavefront_memory_low: fprintf(stream,"MLow)"); break; - case wavefront_memory_ultralow: fprintf(stream,"BiWFA)"); break; + case wavefront_memory_high: fprintf(stream,"MHigh"); break; + case wavefront_memory_med: fprintf(stream,"MMed"); break; + case wavefront_memory_low: fprintf(stream,"MLow"); break; + case wavefront_memory_ultralow: fprintf(stream,"BiWFA"); break; + } + if (wf_aligner->system.max_alignment_steps == INT_MAX) { + fprintf(stream,",inf)"); + } else { + fprintf(stream,",%d)",wf_aligner->system.max_alignment_steps); } } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.h index e5b32112..00e30a4b 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_aligner.h @@ -37,3 +37,34 @@ #include "system/mm_stack.h" #include "alignment/cigar.h" #include "wfa.h" + +/* + * Initialize Aligner (to perform a new alignment) + */ +void wavefront_aligner_init( + wavefront_aligner_t* const wf_aligner, + const int align_level); + +/* + * Utils + */ +uint64_t wavefront_aligner_get_size( + wavefront_aligner_t* const wf_aligner); + +bool wavefront_aligner_maxtrim_cigar( + wavefront_aligner_t* const wf_aligner); + +/* + * Display + */ +void wavefront_aligner_print_mode( + FILE* const stream, + wavefront_aligner_t* const wf_aligner); +void wavefront_aligner_print_scope( + FILE* const stream, + wavefront_aligner_t* const wf_aligner); +void wavefront_aligner_print_conf( + FILE* const stream, + wavefront_aligner_t* const wf_aligner); + + diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c index d6427a2f..fe64ce61 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.c @@ -41,14 +41,12 @@ wavefront_aligner_attr_t wavefront_aligner_attr_default = { .alignment_scope = compute_alignment, .alignment_form = { .span = alignment_end2end, + .extension = false, .pattern_begin_free = 0, .pattern_end_free = 0, .text_begin_free = 0, .text_end_free = 0, }, - // Custom matching functions - .match_funct = NULL, // Use default match-compare function - .match_funct_arguments = NULL, // No arguments // Penalties .linear_penalties = { .match = 0, @@ -88,7 +86,7 @@ wavefront_aligner_attr_t wavefront_aligner_attr_default = { }, // System .system = { - .max_alignment_score = INT_MAX, // Unlimited + .max_alignment_steps = INT_MAX, // Unlimited .probe_interval_global = 3000, .probe_interval_compact = 6000, .max_memory_compact = -1, // Automatically set based on memory-mode diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h index bac851af..41c4a6b9 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_attributes.h @@ -32,6 +32,7 @@ #ifndef WAVEFRONT_ATTRIBUTES_H_ #define WAVEFRONT_ATTRIBUTES_H_ +#include "utils/commons.h" #include "alignment/cigar.h" #include "alignment/affine_penalties.h" #include "alignment/affine2p_penalties.h" @@ -58,6 +59,8 @@ typedef enum { typedef struct { // Mode alignment_span_t span; // Alignment form (End-to-end/Ends-free) + // Extension + bool extension; // Activate extension-like alignment // Ends-free int pattern_begin_free; // Allow free-gap at the beginning of the pattern int pattern_end_free; // Allow free-gap at the end of the pattern @@ -65,32 +68,12 @@ typedef struct { int text_end_free; // Allow free-gap at the end of the text } alignment_form_t; -/* - * Custom extend-match function, e.g.: - * - * typedef struct { - * char* pattern; - * int pattern_length; - * char* text; - * int text_length; - * } match_function_params_t; - * - * int match_function(int v,int h,void* arguments) { - * // Extract parameters - * match_function_params_t* match_arguments = (match_function_params_t*)arguments; - * // Check match - * if (v > match_arguments->pattern_length || h > match_arguments->text_length) return 0; - * return (match_arguments->pattern[v] == match_arguments->text[h]); - * } - */ -typedef int (*alignment_match_funct_t)(int,int,void*); - /* * Alignment system configuration */ typedef struct { // Limits - int max_alignment_score; // Maximum score allowed before quit + int max_alignment_steps; // Maximum WFA-steps allowed before quit // Probing intervals int probe_interval_global; // Score-ticks interval to check any limits int probe_interval_compact; // Score-ticks interval to check BT-buffer compacting @@ -141,9 +124,6 @@ typedef struct { wavefront_heuristic_t heuristic; // Wavefront heuristic // Memory model wavefront_memory_t memory_mode; // Wavefront memory strategy (modular wavefronts and piggyback) - // Custom function to compare sequences - alignment_match_funct_t match_funct; // Custom matching function (match(v,h,args)) - void* match_funct_arguments; // Generic arguments passed to matching function (args) // External MM (instead of allocating one inside) mm_allocator_t* mm_allocator; // MM-Allocator // Display diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c index fbb39060..39a3d793 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace.c @@ -226,12 +226,14 @@ void wavefront_backtrace_linear( const int alignment_k, const wf_offset_t alignment_offset) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; const wavefront_penalties_t* const penalties = &wf_aligner->penalties; const distance_metric_t distance_metric = penalties->distance_metric; // Prepare cigar cigar_t* const cigar = wf_aligner->cigar; + cigar_clear(cigar); cigar->end_offset = cigar->max_operations - 1; cigar->begin_offset = cigar->max_operations - 2; cigar->operations[cigar->end_offset] = '\0'; @@ -323,12 +325,14 @@ void wavefront_backtrace_affine( const int alignment_k, const wf_offset_t alignment_offset) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; const wavefront_penalties_t* const penalties = &wf_aligner->penalties; const distance_metric_t distance_metric = penalties->distance_metric; // Prepare cigar cigar_t* const cigar = wf_aligner->cigar; + cigar_clear(cigar); cigar->end_offset = cigar->max_operations - 1; cigar->begin_offset = cigar->max_operations - 2; cigar->operations[cigar->end_offset] = '\0'; @@ -514,8 +518,8 @@ void wavefront_backtrace_affine( // DEBUG if (v != 0 || h != 0 || (score != 0 && penalties->match == 0)) { fprintf(stderr,"[WFA::Backtrace] I?/D?-Beginning backtrace error\n"); - fprintf(stderr,">%.*s\n",pattern_length,wf_aligner->pattern); - fprintf(stderr,"<%.*s\n",text_length,wf_aligner->text); + fprintf(stderr,">%.*s\n",pattern_length,sequences->pattern); + fprintf(stderr,"<%.*s\n",text_length,sequences->text); exit(-1); } } @@ -550,18 +554,12 @@ void wavefront_backtrace_pcigar( const int end_v = WAVEFRONT_V(alignment_k,alignment_offset); const int end_h = WAVEFRONT_H(alignment_k,alignment_offset); if (wf_aligner->penalties.distance_metric <= gap_linear) { - wf_backtrace_buffer_unpack_cigar_linear(bt_buffer, - wf_aligner->pattern,wf_aligner->pattern_length, - wf_aligner->text,wf_aligner->text_length, - wf_aligner->match_funct, - wf_aligner->match_funct_arguments, + wf_backtrace_buffer_unpack_cigar_linear( + bt_buffer,&wf_aligner->sequences, begin_v,begin_h,end_v,end_h,wf_aligner->cigar); } else { - wf_backtrace_buffer_unpack_cigar_affine(bt_buffer, - wf_aligner->pattern,wf_aligner->pattern_length, - wf_aligner->text,wf_aligner->text_length, - wf_aligner->match_funct, - wf_aligner->match_funct_arguments, + wf_backtrace_buffer_unpack_cigar_affine( + bt_buffer,&wf_aligner->sequences, begin_v,begin_h,end_v,end_h,wf_aligner->cigar); } } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c index ab101279..ce81e1f5 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.c @@ -31,6 +31,7 @@ #include "utils/commons.h" #include "wavefront_backtrace_buffer.h" +#include "wavefront_sequences.h" /* * Config @@ -266,21 +267,18 @@ bt_block_t* wf_backtrace_buffer_traceback_pcigar( } void wf_backtrace_buffer_unpack_cigar_linear( wf_backtrace_buffer_t* const bt_buffer, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, const int begin_v, const int begin_h, const int end_v, const int end_h, cigar_t* const cigar) { - // Clear cigar - char* cigar_buffer = cigar->operations; - cigar->begin_offset = 0; + // Parameters + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // Add init insertions/deletions + cigar_clear(cigar); + char* cigar_buffer = cigar->operations; int i; int v = begin_v; int h = begin_h; @@ -293,9 +291,7 @@ void wf_backtrace_buffer_unpack_cigar_linear( // Unpack block int cigar_block_length = 0; pcigar_unpack_linear( - palignment_blocks[i], - pattern,pattern_length,text,text_length, - match_funct,match_funct_arguments,&v,&h, + palignment_blocks[i],sequences,&v,&h, cigar_buffer,&cigar_block_length); // Update CIGAR cigar_buffer += cigar_block_length; @@ -314,21 +310,18 @@ void wf_backtrace_buffer_unpack_cigar_linear( } void wf_backtrace_buffer_unpack_cigar_affine( wf_backtrace_buffer_t* const bt_buffer, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, const int begin_v, const int begin_h, const int end_v, const int end_h, cigar_t* const cigar) { - // Clear cigar - char* cigar_buffer = cigar->operations; - cigar->begin_offset = 0; + // Parameters + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // Add init insertions/deletions + cigar_clear(cigar); + char* cigar_buffer = cigar->operations; int i; int v = begin_v; int h = begin_h; @@ -342,9 +335,7 @@ void wf_backtrace_buffer_unpack_cigar_affine( // Unpack block int cigar_block_length = 0; pcigar_unpack_affine( - palignment_blocks[i], - pattern,pattern_length,text,text_length, - match_funct,match_funct_arguments,&v,&h, + palignment_blocks[i],sequences,&v,&h, cigar_buffer,&cigar_block_length,¤t_matrix_type); // Update CIGAR cigar_buffer += cigar_block_length; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h index 392b8c8c..3b2f8084 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_buffer.h @@ -119,12 +119,7 @@ bt_block_t* wf_backtrace_buffer_traceback_pcigar( bt_block_t* bt_block); void wf_backtrace_buffer_unpack_cigar_linear( wf_backtrace_buffer_t* const bt_buffer, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, const int begin_v, const int begin_h, const int end_v, @@ -132,12 +127,7 @@ void wf_backtrace_buffer_unpack_cigar_linear( cigar_t* const cigar); void wf_backtrace_buffer_unpack_cigar_affine( wf_backtrace_buffer_t* const bt_buffer, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, const int begin_v, const int begin_h, const int end_v, diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c index f802bbb7..fc8c0690 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_backtrace_offload.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "wfa.h" -#include "utils/string_padded.h" #include "wavefront_backtrace_offload.h" /* diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c index 2ecd41b6..7faca6b0 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.c @@ -47,6 +47,7 @@ */ #define WF_BIALIGN_FALLBACK_MIN_SCORE 250 #define WF_BIALIGN_FALLBACK_MIN_LENGTH 100 +#define WF_BIALIGN_RECOVERY_MIN_SCORE 500 /* * Debug @@ -72,6 +73,116 @@ void wavefront_bialign_debug( } fprintf(stderr,")\n"); } +/* + * Init + */ +void wavefront_bialign_init( + wavefront_bialigner_t* const bialigner, + const distance_metric_t distance_metric, + alignment_form_t* const form, + const affine2p_matrix_type component_begin, + const affine2p_matrix_type component_end, + const int align_level, + const int verbose) { + // Parameters + wavefront_aligner_t* const wf_forward = bialigner->wf_forward; + wavefront_aligner_t* const wf_reverse = bialigner->wf_reverse; + // Configure WF-compute function + switch (distance_metric) { + case indel: + case edit: + bialigner->wf_align_compute = &wavefront_compute_edit; + break; + case gap_linear: + bialigner->wf_align_compute = &wavefront_compute_linear; + break; + case gap_affine: + bialigner->wf_align_compute = &wavefront_compute_affine; + break; + case gap_affine_2p: + bialigner->wf_align_compute = &wavefront_compute_affine2p; + break; + default: + fprintf(stderr,"[WFA] Distance function not implemented\n"); + exit(1); + break; + } + // Initialize wavefront-aligner (forward) + alignment_span_t span_forward = + (form->pattern_begin_free > 0 || form->text_begin_free > 0) ? + alignment_endsfree : alignment_end2end; + alignment_form_t form_forward = { + .span = span_forward, + .pattern_begin_free = form->pattern_begin_free, + .pattern_end_free = 0, + .text_begin_free = form->text_begin_free, + .text_end_free = 0, + }; + wf_forward->alignment_form = form_forward; + wf_forward->component_begin = component_begin; + wf_forward->component_end = component_end; + wavefront_aligner_init(wf_forward,align_level); + // Initialize wavefront-aligner (reverse) + alignment_span_t span_reverse = + (form->pattern_end_free > 0 || form->text_end_free > 0) ? + alignment_endsfree : alignment_end2end; + alignment_form_t form_reverse = { + .span = span_reverse, + .pattern_begin_free = form->pattern_end_free, + .pattern_end_free = 0, + .text_begin_free = form->text_end_free, + .text_end_free = 0, + }; + wf_reverse->alignment_form = form_reverse; + wf_reverse->component_begin = component_end; + wf_reverse->component_end = component_begin; + wavefront_aligner_init(wf_reverse,align_level); + // Plot + const bool plot_enabled = (wf_forward->plot != NULL); + if (plot_enabled) { + wavefront_plot(wf_forward,0,align_level); + wavefront_plot(wf_reverse,0,align_level); + } + // DEBUG + if (verbose >= 2) { + wavefront_debug_begin(wf_forward); + wavefront_debug_begin(wf_reverse); + } +} +/* + * Bidirectional Alignment (base cases) + */ +int wavefront_bialign_base( + wavefront_aligner_t* const wf_aligner, + alignment_form_t* const form, + const affine2p_matrix_type component_begin, + const affine2p_matrix_type component_end, + const int align_level) { + // Parameters + wavefront_aligner_t* const wf_base = wf_aligner->bialigner->wf_base; + const int verbose = wf_base->system.verbose; + // Configure + wf_base->alignment_form = *form; + wavefront_unialign_init(wf_base,component_begin,component_end); + // DEBUG + if (verbose >= 2) wavefront_debug_begin(wf_base); + // Wavefront align sequences + wavefront_unialign(wf_base); + // DEBUG + if (verbose >= 2) { + wavefront_debug_end(wf_base); + wavefront_debug_check_correct(wf_base); + } + // Append CIGAR + cigar_append_forward(wf_aligner->cigar,wf_base->cigar); + // Set status and return + const int align_status = wf_base->align_status.status; + if (align_status == WF_STATUS_ALG_COMPLETED) { + return WF_STATUS_OK; + } else { + return WF_STATUS_UNATTAINABLE; + } +} /* * Bidirectional check breakpoints */ @@ -85,8 +196,9 @@ void wavefront_bialign_breakpoint_indel2indel( const affine2p_matrix_type component, wf_bialign_breakpoint_t* const breakpoint) { // Parameters - const int text_length = wf_aligner->text_length; - const int pattern_length = wf_aligner->pattern_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int text_length = sequences->text_length; + const int pattern_length = sequences->pattern_length; const int gap_open = (component==affine2p_matrix_I1 || component==affine2p_matrix_D1) ? wf_aligner->penalties.gap_opening1 : wf_aligner->penalties.gap_opening2; @@ -108,7 +220,8 @@ void wavefront_bialign_breakpoint_indel2indel( const int dh_0 = WAVEFRONT_H(k_0,doffset_0); const int dh_1 = WAVEFRONT_H(k_1,doffset_1); // Check breakpoint d2d - if (dh_0 + dh_1 >= text_length && score_0 + score_1 - gap_open < breakpoint->score) { + if (dh_0 + dh_1 >= text_length && score_0 + score_1 - gap_open < breakpoint->score && + dh_0 <= text_length && dh_1 <= text_length) { if (breakpoint_forward) { breakpoint->score_forward = score_0; breakpoint->score_reverse = score_1; @@ -141,8 +254,9 @@ void wavefront_bialign_breakpoint_m2m( wavefront_t* const mwf_1, wf_bialign_breakpoint_t* const breakpoint) { // Parameters - const int text_length = wf_aligner->text_length; - const int pattern_length = wf_aligner->pattern_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int text_length = sequences->text_length; + const int pattern_length = sequences->pattern_length; // Check wavefronts overlapping const int lo_0 = mwf_0->lo; const int hi_0 = mwf_0->hi; @@ -270,72 +384,6 @@ void wavefront_bialign_overlap( /* * Bidirectional breakpoint detection */ -void wavefront_bialign_find_breakpoint_init( - wavefront_aligner_t* const alg_forward, - wavefront_aligner_t* const alg_reverse, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const distance_metric_t distance_metric, - alignment_form_t* const form, - const affine2p_matrix_type component_begin, - const affine2p_matrix_type component_end) { - // Resize wavefront aligner - wavefront_unialign_resize(alg_forward,pattern,pattern_length,text,text_length,false); - wavefront_unialign_resize(alg_reverse,pattern,pattern_length,text,text_length,true); - // Configure form forward and reverse - alignment_span_t span_forward = - (form->pattern_begin_free > 0 || form->text_begin_free > 0) ? alignment_endsfree : alignment_end2end; - alignment_form_t form_forward = { - .span = span_forward, - .pattern_begin_free = form->pattern_begin_free, - .pattern_end_free = 0, - .text_begin_free = form->text_begin_free, - .text_end_free = 0, - }; - alignment_span_t span_reverse = - (form->pattern_end_free > 0 || form->text_end_free > 0) ? alignment_endsfree : alignment_end2end; - alignment_form_t form_reverse = { - .span = span_reverse, - .pattern_begin_free = form->pattern_end_free, - .pattern_end_free = 0, - .text_begin_free = form->text_end_free, - .text_end_free = 0, - }; - // Configure WF-compute function (global) - switch (distance_metric) { - case indel: - case edit: - alg_forward->align_status.wf_align_compute = &wavefront_compute_edit; - break; - case gap_linear: - alg_forward->align_status.wf_align_compute = &wavefront_compute_linear; - break; - case gap_affine: - alg_forward->align_status.wf_align_compute = &wavefront_compute_affine; - break; - case gap_affine_2p: - alg_forward->align_status.wf_align_compute = &wavefront_compute_affine2p; - break; - default: - fprintf(stderr,"[WFA] Distance function not implemented\n"); - exit(1); - break; - } - // Initialize wavefront (forward) - alg_forward->align_status.num_null_steps = 0; - alg_forward->alignment_form = form_forward; - alg_forward->component_begin = component_begin; - alg_forward->component_end = component_end; - wavefront_unialign_initialize_wavefronts(alg_forward,pattern_length,text_length); - // Initialize wavefront (reverse) - alg_reverse->align_status.num_null_steps = 0; - alg_reverse->alignment_form = form_reverse; - alg_reverse->component_begin = component_end; - alg_reverse->component_end = component_begin; - wavefront_unialign_initialize_wavefronts(alg_reverse,pattern_length,text_length); -} int wavefront_bialign_overlap_gopen_adjust( wavefront_aligner_t* const wf_aligner, const distance_metric_t distance_metric) { @@ -353,10 +401,6 @@ int wavefront_bialign_overlap_gopen_adjust( } int wavefront_bialign_find_breakpoint( wavefront_bialigner_t* const bialigner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, const distance_metric_t distance_metric, alignment_form_t* const form, const affine2p_matrix_type component_begin, @@ -364,41 +408,33 @@ int wavefront_bialign_find_breakpoint( wf_bialign_breakpoint_t* const breakpoint, const int align_level) { // Parameters - wavefront_aligner_t* const alg_forward = bialigner->alg_forward; - wavefront_aligner_t* const alg_reverse = bialigner->alg_reverse; - // Init bialignment - wavefront_bialign_find_breakpoint_init( - alg_forward,alg_reverse, - pattern,pattern_length,text,text_length, - distance_metric,form,component_begin,component_end); - // DEBUG - alignment_system_t* const system = &alg_forward->system; + wavefront_aligner_t* const wf_forward = bialigner->wf_forward; + wavefront_aligner_t* const wf_reverse = bialigner->wf_reverse; + alignment_system_t* const system = &wf_forward->system; + const bool plot_enabled = (wf_forward->plot != NULL); const int verbose = system->verbose; - if (verbose >= 2) { - wavefront_debug_prologue(alg_forward,pattern,pattern_length,text,text_length); - wavefront_debug_prologue(alg_reverse,pattern,pattern_length,text,text_length); - } + // Init bialignment + wavefront_bialign_init(bialigner,distance_metric,form,component_begin,component_end,align_level,verbose); + // Sequences + wavefront_sequences_t* const sequences = &wf_forward->sequences; + const int text_length = sequences->text_length; + const int pattern_length = sequences->pattern_length; + // Operators + void (*wf_align_compute)(wavefront_aligner_t* const,const int) = bialigner->wf_align_compute; // Parameters - const int max_alignment_score = alg_forward->system.max_alignment_score; + const int max_alignment_steps = wf_forward->system.max_alignment_steps; const int max_antidiagonal = DPMATRIX_ANTIDIAGONAL(pattern_length,text_length) - 1; // Note: Even removing -1 - void (*wf_align_compute)(wavefront_aligner_t* const,const int) = alg_forward->align_status.wf_align_compute; int score_forward = 0, score_reverse = 0, forward_max_ak = 0, reverse_max_ak = 0; - bool end_reached; - // Plot - const bool plot_enabled = (alg_forward->plot != NULL); - if (plot_enabled) { - wavefront_plot(alg_forward,0,align_level); - wavefront_plot(alg_reverse,0,align_level); - } + bool reachability_quit; // Prepare and perform first bialignment step breakpoint->score = INT_MAX; - end_reached = wavefront_extend_end2end_max(alg_forward,score_forward,&forward_max_ak); - if (end_reached) return alg_forward->align_status.status; - end_reached = wavefront_extend_end2end_max(alg_reverse,score_reverse,&reverse_max_ak); - if (end_reached) return alg_reverse->align_status.status; + reachability_quit = wavefront_extend_end2end_max(wf_forward,score_forward,&forward_max_ak); + if (reachability_quit) return wf_forward->align_status.status; + reachability_quit = wavefront_extend_end2end_max(wf_reverse,score_reverse,&reverse_max_ak); + if (reachability_quit) return wf_reverse->align_status.status; // Compute wavefronts of increasing score until both wavefronts overlap int max_ak = 0; - bool last_wf_forward; + bool last_wf_forward = false; while (true) { // Check close-to-collision if (forward_max_ak + reverse_max_ak >= max_antidiagonal) break; @@ -406,150 +442,99 @@ int wavefront_bialign_find_breakpoint( * Compute next wavefront (Forward) */ ++score_forward; - (*wf_align_compute)(alg_forward,score_forward); - if (plot_enabled) wavefront_plot(alg_forward,score_forward,align_level); // Plot + (*wf_align_compute)(wf_forward,score_forward); + if (plot_enabled) wavefront_plot(wf_forward,score_forward,align_level); // Plot // Extend - end_reached = wavefront_extend_end2end_max(alg_forward,score_forward,&max_ak); + reachability_quit = wavefront_extend_end2end_max(wf_forward,score_forward,&max_ak); if (forward_max_ak < max_ak) forward_max_ak = max_ak; last_wf_forward = true; // Check end-reached and close-to-collision - if (end_reached) return alg_forward->align_status.status; + if (reachability_quit) return wf_forward->align_status.status; if (forward_max_ak + reverse_max_ak >= max_antidiagonal) break; /* * Compute next wavefront (Reverse) */ ++score_reverse; - (*wf_align_compute)(alg_reverse,score_reverse); - if (plot_enabled) wavefront_plot(alg_reverse,score_reverse,align_level); // Plot + (*wf_align_compute)(wf_reverse,score_reverse); + if (plot_enabled) wavefront_plot(wf_reverse,score_reverse,align_level); // Plot // Extend - end_reached = wavefront_extend_end2end_max(alg_reverse,score_reverse,&max_ak); + reachability_quit = wavefront_extend_end2end_max(wf_reverse,score_reverse,&max_ak); if (reverse_max_ak < max_ak) reverse_max_ak = max_ak; last_wf_forward = false; - // Check end-reached and max-score-reached - if (end_reached) return alg_reverse->align_status.status; - if (score_reverse + score_forward >= max_alignment_score) return WF_STATUS_MAX_SCORE_REACHED; + // Check end-reached and max-steps-reached + if (reachability_quit) return wf_reverse->align_status.status; + if (score_reverse + score_forward >= max_alignment_steps) return WF_STATUS_MAX_STEPS_REACHED; // DEBUG if (verbose >= 3 && score_forward % system->probe_interval_global == 0) { - wavefront_unialign_print_status(stderr,alg_forward,score_forward); + wavefront_unialign_print_status(stderr,wf_forward,score_forward); } } // Advance until overlap is found - const int max_score_scope = alg_forward->wf_components.max_score_scope; - const int gap_opening = wavefront_bialign_overlap_gopen_adjust(alg_forward,distance_metric); + const int max_score_scope = wf_forward->wf_components.max_score_scope; + const int gap_opening = wavefront_bialign_overlap_gopen_adjust(wf_forward,distance_metric); while (true) { if (last_wf_forward) { // Check overlapping wavefronts const int min_score_reverse = (score_reverse > max_score_scope-1) ? score_reverse - (max_score_scope-1) : 0; if (score_forward + min_score_reverse - gap_opening >= breakpoint->score) break; // Done! - wavefront_bialign_overlap(alg_forward,alg_reverse,score_forward,score_reverse,true,breakpoint); + wavefront_bialign_overlap(wf_forward,wf_reverse,score_forward,score_reverse,true,breakpoint); /* * Compute next wavefront (Reverse) */ ++score_reverse; - (*wf_align_compute)(alg_reverse,score_reverse); - if (plot_enabled) wavefront_plot(alg_reverse,score_reverse,align_level); // Plot + (*wf_align_compute)(wf_reverse,score_reverse); + if (plot_enabled) wavefront_plot(wf_reverse,score_reverse,align_level); // Plot // Extend & check end-reached - end_reached = wavefront_extend_end2end(alg_reverse,score_reverse); - if (end_reached) return alg_reverse->align_status.status; + reachability_quit = wavefront_extend_end2end(wf_reverse,score_reverse); + if (reachability_quit) return wf_reverse->align_status.status; } // Check overlapping wavefronts const int min_score_forward = (score_forward > max_score_scope-1) ? score_forward - (max_score_scope-1) : 0; if (min_score_forward + score_reverse - gap_opening >= breakpoint->score) break; // Done! - wavefront_bialign_overlap(alg_reverse,alg_forward,score_reverse,score_forward,false,breakpoint); + wavefront_bialign_overlap(wf_reverse,wf_forward,score_reverse,score_forward,false,breakpoint); /* * Compute next wavefront (Forward) */ ++score_forward; - (*wf_align_compute)(alg_forward,score_forward); - if (plot_enabled) wavefront_plot(alg_forward,score_forward,align_level); // Plot - // Extend & check end-reached/max-score-reached - end_reached = wavefront_extend_end2end(alg_forward,score_forward); - if (end_reached) return alg_forward->align_status.status; - if (score_reverse + score_forward >= max_alignment_score) return WF_STATUS_MAX_SCORE_REACHED; + (*wf_align_compute)(wf_forward,score_forward); + if (plot_enabled) wavefront_plot(wf_forward,score_forward,align_level); // Plot + // Extend & check end-reached/max-steps-reached + reachability_quit = wavefront_extend_end2end(wf_forward,score_forward); + if (reachability_quit) return wf_forward->align_status.status; + if (score_reverse + score_forward >= max_alignment_steps) return WF_STATUS_MAX_STEPS_REACHED; // Enable always last_wf_forward = true; } // Return OK - return WF_STATUS_SUCCESSFUL; -} -/* - * Bidirectional Alignment (base cases) - */ -void wavefront_bialign_base( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_form_t* const form, - const affine2p_matrix_type component_begin, - const affine2p_matrix_type component_end, - const int align_level) { - // Parameters - wavefront_aligner_t* const alg_subsidiary = wf_aligner->bialigner->alg_subsidiary; - const int verbose = wf_aligner->system.verbose; - // Configure - alg_subsidiary->alignment_form = *form; - wavefront_unialign_init( - alg_subsidiary,pattern,pattern_length, - text,text_length,component_begin,component_end); - // DEBUG - if (verbose >= 2) { - wavefront_debug_prologue(alg_subsidiary,pattern,pattern_length,text,text_length); - } - // Wavefront align sequences - wavefront_unialign(alg_subsidiary); - wf_aligner->align_status.status = alg_subsidiary->align_status.status; - // DEBUG - if (verbose >= 2) { - wavefront_debug_epilogue(alg_subsidiary); - wavefront_debug_check_correct(wf_aligner); - } - // Append CIGAR - cigar_append(wf_aligner->cigar,alg_subsidiary->cigar); - if (align_level == 0) wf_aligner->cigar->score = alg_subsidiary->cigar->score; + return WF_STATUS_OK; } -void wavefront_bialign_exception( +int wavefront_bialign_find_breakpoint_exception( wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, alignment_form_t* const form, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end, const int align_level, const int align_status) { - // Check max-score reached or unfeasible alignment - if (align_status == WF_STATUS_MAX_SCORE_REACHED || - align_status == WF_STATUS_UNFEASIBLE) { - wf_aligner->align_status.status = align_status; - return; - } - // Check end reached + // Breakpoint was not found, check end reached if (align_status == WF_STATUS_END_REACHED) { - wavefront_aligner_t* const alg_forward = wf_aligner->bialigner->alg_forward; - wavefront_aligner_t* const alg_reverse = wf_aligner->bialigner->alg_reverse; + wavefront_aligner_t* const wf_forward = wf_aligner->bialigner->wf_forward; + wavefront_aligner_t* const wf_reverse = wf_aligner->bialigner->wf_reverse; // Retrieve score when end was reached int score_reached; - if (alg_forward->align_status.status == WF_STATUS_END_REACHED) { - score_reached = alg_forward->align_status.score; + if (wf_forward->align_status.status == WF_STATUS_END_REACHED) { + score_reached = wf_forward->align_status.score; } else { - score_reached = alg_reverse->align_status.score; + score_reached = wf_reverse->align_status.score; } // Fallback if possible - if (score_reached <= WF_BIALIGN_FALLBACK_MIN_SCORE) { - wavefront_bialign_base( - wf_aligner,pattern,pattern_length,text,text_length, - form,component_begin,component_end,align_level); + if (score_reached <= WF_BIALIGN_RECOVERY_MIN_SCORE) { + return wavefront_bialign_base(wf_aligner,form,component_begin,component_end,align_level); } else { - wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; + return WF_STATUS_END_UNREACHABLE; // To no avail } - return; + } else { // Other unrecoverable conditions + return align_status; } - // Otherwise - fprintf(stderr,"[WFA::BiAlign] Unknown condition\n"); - exit(1); } /* * Bidirectional Alignment @@ -563,6 +548,7 @@ void wavefront_bialign_init_half_0( global_form->text_begin_free > 0) ? alignment_endsfree : alignment_end2end; half_form->span = span_0; + half_form->extension = false; half_form->pattern_begin_free = global_form->pattern_begin_free; half_form->pattern_end_free = 0; half_form->text_begin_free = global_form->text_begin_free; @@ -577,170 +563,159 @@ void wavefront_bialign_init_half_1( global_form->text_begin_free > 0) ? alignment_endsfree : alignment_end2end; half_form->span = span_1; + half_form->extension = false; half_form->pattern_begin_free = 0; half_form->pattern_end_free = global_form->pattern_end_free; half_form->text_begin_free = 0; half_form->text_end_free = global_form->text_end_free; } -void wavefront_bialign_alignment( +int wavefront_bialign_alignment( wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_begin, - const int pattern_end, - const char* const text, - const int text_begin, - const int text_end, alignment_form_t* const form, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end, const int score_remaining, const int align_level) { // Parameters + wavefront_sequences_t* const sequences = &wf_aligner->bialigner->wf_forward->sequences; + const int pattern_begin = sequences->pattern_begin; + const int pattern_end = sequences->pattern_begin + sequences->pattern_length; + const int text_begin = sequences->text_begin; + const int text_end = sequences->text_begin + sequences->text_length; const int pattern_length = pattern_end - pattern_begin; const int text_length = text_end - text_begin; // Trivial cases if (text_length == 0) { cigar_append_deletion(wf_aligner->cigar,pattern_length); - return; + return WF_STATUS_OK; } else if (pattern_length == 0) { cigar_append_insertion(wf_aligner->cigar,text_length); - return; - } - // Fall back to regular WFA - if (score_remaining <= WF_BIALIGN_FALLBACK_MIN_SCORE) { - wavefront_bialign_base(wf_aligner, - pattern+pattern_begin,pattern_length, - text+text_begin,text_length, - form,component_begin,component_end,align_level); - return; + return WF_STATUS_OK; + } else if (score_remaining <= WF_BIALIGN_FALLBACK_MIN_SCORE) { + // Fall back to regular WFA + return wavefront_bialign_base(wf_aligner,form, + component_begin,component_end,align_level); } // Find breakpoint in the alignment wf_bialign_breakpoint_t breakpoint; - const int align_status = wavefront_bialign_find_breakpoint( - wf_aligner->bialigner, - pattern+pattern_begin,pattern_length, - text+text_begin,text_length, - wf_aligner->penalties.distance_metric, - form,component_begin,component_end, - &breakpoint,align_level); + int align_status = wavefront_bialign_find_breakpoint( + wf_aligner->bialigner,wf_aligner->penalties.distance_metric, + form,component_begin,component_end,&breakpoint,align_level); // DEBUG if (wf_aligner->system.verbose >= 2) { - wavefront_debug_epilogue(wf_aligner->bialigner->alg_forward); - wavefront_debug_epilogue(wf_aligner->bialigner->alg_reverse); + wf_aligner->bialigner->wf_forward->align_status.status = align_status; + wf_aligner->bialigner->wf_reverse->align_status.status = align_status; + wavefront_debug_end(wf_aligner->bialigner->wf_forward); + wavefront_debug_end(wf_aligner->bialigner->wf_reverse); } // Check status - if (align_status != WF_STATUS_SUCCESSFUL) { - wavefront_bialign_exception(wf_aligner, - pattern+pattern_begin,pattern_length, - text+text_begin,text_length, - form,component_begin,component_end,align_level,align_status); - return; + if (align_status != WF_STATUS_OK) { + return wavefront_bialign_find_breakpoint_exception( + wf_aligner,form,component_begin,component_end,align_level,align_status); } // Breakpoint found const int breakpoint_h = WAVEFRONT_H(breakpoint.k_forward,breakpoint.offset_forward); const int breakpoint_v = WAVEFRONT_V(breakpoint.k_forward,breakpoint.offset_forward); // DEBUG if (wf_aligner->system.verbose >= 3) wavefront_bialign_debug(&breakpoint,align_level); - // Parameters - wavefront_plot_t* const plot = wf_aligner->plot; // Align half_0 alignment_form_t form_0; - if (plot) { - plot->offset_v = pattern_begin; - plot->offset_h = text_begin; - } + wavefront_bialigner_set_sequences_bounds(wf_aligner->bialigner, + pattern_begin,pattern_begin+breakpoint_v, + text_begin,text_begin+breakpoint_h); wavefront_bialign_init_half_0(form,&form_0); - wavefront_bialign_alignment(wf_aligner, - pattern,pattern_begin,pattern_begin+breakpoint_v, - text,text_begin,text_begin+breakpoint_h, + align_status = wavefront_bialign_alignment(wf_aligner, &form_0,component_begin,breakpoint.component, breakpoint.score_forward,align_level+1); - if (wf_aligner->align_status.status != WF_STATUS_SUCCESSFUL) return; + if (align_status != WF_STATUS_OK) return align_status; // Align half_1 alignment_form_t form_1; - if (plot) { - plot->offset_v = pattern_begin + breakpoint_v; - plot->offset_h = text_begin + breakpoint_h; - } + wavefront_bialigner_set_sequences_bounds(wf_aligner->bialigner, + pattern_begin+breakpoint_v,pattern_end, + text_begin+breakpoint_h,text_end); wavefront_bialign_init_half_1(form,&form_1); - wavefront_bialign_alignment(wf_aligner, - pattern,pattern_begin+breakpoint_v,pattern_end, - text,text_begin+breakpoint_h,text_end, + align_status = wavefront_bialign_alignment(wf_aligner, &form_1,breakpoint.component,component_end, breakpoint.score_reverse,align_level+1); - if (wf_aligner->align_status.status != WF_STATUS_SUCCESSFUL) return; - // Set score - wf_aligner->cigar->score = wavefront_compute_classic_score( - wf_aligner,pattern_length,text_length,breakpoint.score); + if (align_status != WF_STATUS_OK) return align_status; + // Set score (Strictly speaking, only needed at level-0) + if (align_level == 0) { + cigar_t* const cigar = wf_aligner->cigar; + cigar->score = wavefront_compute_classic_score(wf_aligner,pattern_length,text_length,breakpoint.score); + cigar->end_v = pattern_length; + cigar->end_h = text_length; + } + return WF_STATUS_OK; // All good } /* * Bidirectional Score-only */ -void wavefront_bialign_compute_score( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length) { +int wavefront_bialign_compute_score( + wavefront_aligner_t* const wf_aligner) { + // Parameters + wavefront_aligner_t* const wf_forward = wf_aligner->bialigner->wf_forward; + wavefront_aligner_t* const wf_reverse = wf_aligner->bialigner->wf_reverse; + wavefront_sequences_t* const sequences = &wf_forward->sequences; + const int text_length = sequences->text_length; + const int pattern_length = sequences->pattern_length; + // Clear cigar + cigar_clear(wf_aligner->cigar); // Find breakpoint in the alignment wf_bialign_breakpoint_t breakpoint; - const int align_status = wavefront_bialign_find_breakpoint( - wf_aligner->bialigner,pattern,pattern_length,text,text_length, + const int align_status = wavefront_bialign_find_breakpoint(wf_aligner->bialigner, wf_aligner->penalties.distance_metric,&wf_aligner->alignment_form, affine_matrix_M,affine_matrix_M,&breakpoint,0); // DEBUG if (wf_aligner->system.verbose >= 2) { - wavefront_debug_epilogue(wf_aligner->bialigner->alg_forward); - wavefront_debug_epilogue(wf_aligner->bialigner->alg_reverse); + wavefront_debug_end(wf_forward); + wavefront_debug_end(wf_reverse); } // Check status - if (align_status == WF_STATUS_MAX_SCORE_REACHED || align_status == WF_STATUS_UNFEASIBLE) { - wf_aligner->align_status.status = align_status; - return; - } - if (align_status == WF_STATUS_END_REACHED) { - wavefront_aligner_t* const alg_forward = wf_aligner->bialigner->alg_forward; - wavefront_aligner_t* const alg_reverse = wf_aligner->bialigner->alg_reverse; - if (alg_forward->align_status.status == WF_STATUS_END_REACHED) { - breakpoint.score = alg_forward->align_status.score; - } else { - breakpoint.score = alg_reverse->align_status.score; + cigar_t* const cigar = wf_aligner->cigar; + if (align_status == WF_STATUS_OK || align_status == WF_STATUS_END_REACHED) { + if (align_status == WF_STATUS_END_REACHED) { + breakpoint.score = (wf_forward->align_status.status == WF_STATUS_END_REACHED) ? + wf_forward->align_status.score : wf_reverse->align_status.score; } + // Set status & score + cigar->score = wavefront_compute_classic_score(wf_aligner,pattern_length,text_length,breakpoint.score); + cigar->end_v = pattern_length; + cigar->end_h = text_length; + // Return OK + return WF_STATUS_OK; + } else { + // Other cases + return align_status; } - // Report score - cigar_clear(wf_aligner->cigar); - wf_aligner->cigar->score = wavefront_compute_classic_score( - wf_aligner,pattern_length,text_length,breakpoint.score); - wf_aligner->align_status.status = WF_STATUS_SUCCESSFUL; } /* * Bidirectional dispatcher */ void wavefront_bialign( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length) { - // Init - wf_aligner->align_status.status = WF_STATUS_SUCCESSFUL; // Init OK - // Just for outputting info at plot - wf_aligner->pattern = (char*)pattern; - wf_aligner->pattern_length = pattern_length; - wf_aligner->text = (char*)text; - wf_aligner->text_length = text_length; + wavefront_aligner_t* const wf_aligner) { // Select scope + int align_status; if (wf_aligner->alignment_scope == compute_score) { - wavefront_bialign_compute_score(wf_aligner,pattern,pattern_length,text,text_length); + align_status = wavefront_bialign_compute_score(wf_aligner); } else { - cigar_resize(wf_aligner->cigar,2*(pattern_length+text_length)); + // Resize CIGAR + wavefront_sequences_t* const sequences = &wf_aligner->bialigner->wf_forward->sequences; + const int text_length = sequences->text_length; + const int pattern_length = sequences->pattern_length; + cigar_resize(wf_aligner->cigar,2*(pattern_length+text_length)); // Resize & clear // Bidirectional alignment const bool min_length = MAX(pattern_length,text_length) <= WF_BIALIGN_FALLBACK_MIN_LENGTH; - wavefront_bialign_alignment(wf_aligner, - pattern,0,pattern_length, - text,0,text_length, + align_status = wavefront_bialign_alignment(wf_aligner, &wf_aligner->alignment_form, affine_matrix_M,affine_matrix_M, min_length ? 0 : INT_MAX,0); } + // Check status + if (align_status == WF_STATUS_OK) { + wf_aligner->align_status.status = WF_STATUS_ALG_COMPLETED; + } else if (align_status == WF_STATUS_MAX_STEPS_REACHED || align_status == WF_STATUS_OOM) { + wf_aligner->align_status.status = align_status; + } else { // Other cases + wf_aligner->align_status.status = WF_STATUS_UNATTAINABLE; + } } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h index f13eec6a..7a96a0d6 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialign.h @@ -37,10 +37,6 @@ * Bidirectional WFA */ void wavefront_bialign( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length); + wavefront_aligner_t* const wf_aligner); #endif /* WAVEFRONT_BIALIGN_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c index 260379ee..f8eb7d16 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.c @@ -49,98 +49,151 @@ wavefront_bialigner_t* wavefront_bialigner_new( subsidiary_attr.linear_penalties = attributes->linear_penalties; subsidiary_attr.affine_penalties = attributes->affine_penalties; subsidiary_attr.affine2p_penalties = attributes->affine2p_penalties; - subsidiary_attr.match_funct = attributes->match_funct; - subsidiary_attr.match_funct_arguments = attributes->match_funct_arguments; // Set specifics for subsidiary aligners - subsidiary_attr.heuristic = attributes->heuristic; // Inherit same heuristic + subsidiary_attr.heuristic = attributes->heuristic; // Inherit same heuristic subsidiary_attr.memory_mode = wavefront_memory_high; // Classic WFA - subsidiary_attr.alignment_scope = compute_score; + subsidiary_attr.alignment_scope = compute_score; // BiWFAs are score-only + subsidiary_attr.alignment_form.extension = false; // Deactivate extension mode // Set other parameter for subsidiary aligners - subsidiary_attr.system = attributes->system; + subsidiary_attr.system = attributes->system; // Inherit system configuration // Allocate forward/reverse aligners - wf_bialigner->alg_forward = wavefront_aligner_new(&subsidiary_attr); - wf_bialigner->alg_forward->align_mode = wf_align_biwfa_breakpoint_forward; - wf_bialigner->alg_forward->plot = plot; - wf_bialigner->alg_reverse = wavefront_aligner_new(&subsidiary_attr); - wf_bialigner->alg_reverse->align_mode = wf_align_biwfa_breakpoint_reverse; - wf_bialigner->alg_reverse->plot = plot; + wf_bialigner->wf_forward = wavefront_aligner_new(&subsidiary_attr); + wf_bialigner->wf_forward->align_mode = wf_align_biwfa_breakpoint_forward; + wf_bialigner->wf_forward->plot = plot; + wf_bialigner->wf_reverse = wavefront_aligner_new(&subsidiary_attr); + wf_bialigner->wf_reverse->align_mode = wf_align_biwfa_breakpoint_reverse; + wf_bialigner->wf_reverse->plot = plot; // Allocate subsidiary aligner subsidiary_attr.alignment_scope = compute_alignment; - wf_bialigner->alg_subsidiary = wavefront_aligner_new(&subsidiary_attr); - wf_bialigner->alg_subsidiary->align_mode = wf_align_biwfa_subsidiary; - wf_bialigner->alg_subsidiary->plot = plot; + subsidiary_attr.heuristic.strategy = wf_heuristic_none; // Not inherited + wf_bialigner->wf_base = wavefront_aligner_new(&subsidiary_attr); + wf_bialigner->wf_base->align_mode = wf_align_biwfa_subsidiary; + wf_bialigner->wf_base->plot = plot; // Return return wf_bialigner; } void wavefront_bialigner_reap( wavefront_bialigner_t* const wf_bialigner) { - wavefront_aligner_reap(wf_bialigner->alg_forward); - wavefront_aligner_reap(wf_bialigner->alg_reverse); - wavefront_aligner_reap(wf_bialigner->alg_subsidiary); + wavefront_aligner_reap(wf_bialigner->wf_forward); + wavefront_aligner_reap(wf_bialigner->wf_reverse); + wavefront_aligner_reap(wf_bialigner->wf_base); } void wavefront_bialigner_delete( wavefront_bialigner_t* const wf_bialigner) { - wavefront_aligner_delete(wf_bialigner->alg_forward); - wavefront_aligner_delete(wf_bialigner->alg_reverse); - wavefront_aligner_delete(wf_bialigner->alg_subsidiary); + wavefront_aligner_delete(wf_bialigner->wf_forward); + wavefront_aligner_delete(wf_bialigner->wf_reverse); + wavefront_aligner_delete(wf_bialigner->wf_base); free(wf_bialigner); } +/* + * Sequences + */ +void wavefront_bialigner_set_sequences_ascii( + wavefront_bialigner_t* const wf_bialigner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length) { + wavefront_sequences_init_ascii( + &wf_bialigner->wf_forward->sequences, + pattern,pattern_length,text,text_length,false); + wavefront_sequences_init_ascii( + &wf_bialigner->wf_reverse->sequences, + pattern,pattern_length,text,text_length,true); + wavefront_sequences_init_ascii( + &wf_bialigner->wf_base->sequences, + pattern,pattern_length,text,text_length,false); +} +void wavefront_bialigner_set_sequences_lambda( + wavefront_bialigner_t* const wf_bialigner, + alignment_match_funct_t match_funct, + void* match_funct_arguments, + const int pattern_length, + const int text_length) { + wavefront_sequences_init_lambda(&wf_bialigner->wf_forward->sequences, + match_funct,match_funct_arguments,pattern_length,text_length,false); + wavefront_sequences_init_lambda(&wf_bialigner->wf_reverse->sequences, + match_funct,match_funct_arguments,pattern_length,text_length,true); + wavefront_sequences_init_lambda(&wf_bialigner->wf_base->sequences, + match_funct,match_funct_arguments,pattern_length,text_length,false); +} +void wavefront_bialigner_set_sequences_packed2bits( + wavefront_bialigner_t* const wf_bialigner, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length) { + wavefront_sequences_init_packed2bits( + &wf_bialigner->wf_forward->sequences, + pattern,pattern_length,text,text_length,false); + wavefront_sequences_init_packed2bits( + &wf_bialigner->wf_reverse->sequences, + pattern,pattern_length,text,text_length,true); + wavefront_sequences_init_packed2bits( + &wf_bialigner->wf_base->sequences, + pattern,pattern_length,text,text_length,false); +} +void wavefront_bialigner_set_sequences_bounds( + wavefront_bialigner_t* const wf_bialigner, + const int pattern_begin, + const int pattern_end, + const int text_begin, + const int text_end) { + wavefront_sequences_set_bounds( + &wf_bialigner->wf_forward->sequences, + pattern_begin,pattern_end,text_begin,text_end); + wavefront_sequences_set_bounds( + &wf_bialigner->wf_reverse->sequences, + pattern_begin,pattern_end,text_begin,text_end); + wavefront_sequences_set_bounds( + &wf_bialigner->wf_base->sequences, + pattern_begin,pattern_end,text_begin,text_end); +} /* * Accessors */ uint64_t wavefront_bialigner_get_size( wavefront_bialigner_t* const wf_bialigner) { - return wavefront_aligner_get_size(wf_bialigner->alg_forward) + - wavefront_aligner_get_size(wf_bialigner->alg_reverse) + - wavefront_aligner_get_size(wf_bialigner->alg_subsidiary); + return wavefront_aligner_get_size(wf_bialigner->wf_forward) + + wavefront_aligner_get_size(wf_bialigner->wf_reverse) + + wavefront_aligner_get_size(wf_bialigner->wf_base); } void wavefront_bialigner_set_heuristic( wavefront_bialigner_t* const wf_bialigner, wavefront_heuristic_t* const heuristic) { - wf_bialigner->alg_forward->heuristic = *heuristic; - wf_bialigner->alg_reverse->heuristic = *heuristic; - wf_bialigner->alg_subsidiary->heuristic = *heuristic; + wf_bialigner->wf_forward->heuristic = *heuristic; + wf_bialigner->wf_reverse->heuristic = *heuristic; + // Heuristics are not inherited to wf_base } -void wavefront_bialigner_set_match_funct( +void wavefront_bialigner_set_max_alignment_steps( wavefront_bialigner_t* const wf_bialigner, - int (*match_funct)(int,int,void*), - void* const match_funct_arguments) { - wf_bialigner->alg_forward->match_funct = match_funct; - wf_bialigner->alg_forward->match_funct_arguments = match_funct_arguments; - wf_bialigner->alg_reverse->match_funct = match_funct; - wf_bialigner->alg_reverse->match_funct_arguments = match_funct_arguments; - wf_bialigner->alg_subsidiary->match_funct = match_funct; - wf_bialigner->alg_subsidiary->match_funct_arguments = match_funct_arguments; -} -void wavefront_bialigner_set_max_alignment_score( - wavefront_bialigner_t* const wf_bialigner, - const int max_alignment_score) { - wf_bialigner->alg_forward->system.max_alignment_score = max_alignment_score; - wf_bialigner->alg_reverse->system.max_alignment_score = max_alignment_score; - wf_bialigner->alg_subsidiary->system.max_alignment_score = max_alignment_score; + const int max_alignment_steps) { + wf_bialigner->wf_forward->system.max_alignment_steps = max_alignment_steps; + wf_bialigner->wf_reverse->system.max_alignment_steps = max_alignment_steps; + wf_bialigner->wf_base->system.max_alignment_steps = max_alignment_steps; } void wavefront_bialigner_set_max_memory( wavefront_bialigner_t* const wf_bialigner, const uint64_t max_memory_resident, const uint64_t max_memory_abort) { - wf_bialigner->alg_forward->system.max_memory_resident = max_memory_resident; - wf_bialigner->alg_forward->system.max_memory_abort = max_memory_abort; - wf_bialigner->alg_reverse->system.max_memory_resident = max_memory_resident; - wf_bialigner->alg_reverse->system.max_memory_abort = max_memory_abort; - wf_bialigner->alg_subsidiary->system.max_memory_resident = max_memory_resident; - wf_bialigner->alg_subsidiary->system.max_memory_abort = max_memory_abort; + wf_bialigner->wf_forward->system.max_memory_resident = max_memory_resident; + wf_bialigner->wf_forward->system.max_memory_abort = max_memory_abort; + wf_bialigner->wf_reverse->system.max_memory_resident = max_memory_resident; + wf_bialigner->wf_reverse->system.max_memory_abort = max_memory_abort; + wf_bialigner->wf_base->system.max_memory_resident = max_memory_resident; + wf_bialigner->wf_base->system.max_memory_abort = max_memory_abort; } void wavefront_bialigner_set_max_num_threads( - wavefront_bialigner_t* const wf_bialigner, - const int max_num_threads) { - wf_bialigner->alg_forward->system.max_num_threads = max_num_threads; - wf_bialigner->alg_reverse->system.max_num_threads = max_num_threads; - wf_bialigner->alg_subsidiary->system.max_num_threads = max_num_threads; + wavefront_bialigner_t* const wf_bialigner, + const int max_num_threads) { + wf_bialigner->wf_forward->system.max_num_threads = max_num_threads; + wf_bialigner->wf_reverse->system.max_num_threads = max_num_threads; + wf_bialigner->wf_base->system.max_num_threads = max_num_threads; } void wavefront_bialigner_set_min_offsets_per_thread( - wavefront_bialigner_t* const wf_bialigner, - const int min_offsets_per_thread) { - wf_bialigner->alg_forward->system.min_offsets_per_thread = min_offsets_per_thread; - wf_bialigner->alg_reverse->system.min_offsets_per_thread = min_offsets_per_thread; - wf_bialigner->alg_subsidiary->system.min_offsets_per_thread = min_offsets_per_thread; + wavefront_bialigner_t* const wf_bialigner, + const int min_offsets_per_thread) { + wf_bialigner->wf_forward->system.min_offsets_per_thread = min_offsets_per_thread; + wf_bialigner->wf_reverse->system.min_offsets_per_thread = min_offsets_per_thread; + wf_bialigner->wf_base->system.min_offsets_per_thread = min_offsets_per_thread; } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h index e5781b22..22d64db2 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_bialigner.h @@ -35,6 +35,7 @@ #include "wavefront_attributes.h" #include "wavefront_heuristic.h" #include "wavefront_offset.h" +#include "wavefront_sequences.h" // Wavefront ahead definition typedef struct _wavefront_aligner_t wavefront_aligner_t; @@ -53,9 +54,12 @@ typedef struct { } wf_bialign_breakpoint_t; typedef struct { - wavefront_aligner_t* alg_forward; // Forward aligner - wavefront_aligner_t* alg_reverse; // Reverse aligner - wavefront_aligner_t* alg_subsidiary; // Subsidiary aligner + // Wavefronts + wavefront_aligner_t* wf_forward; // Breakpoint Forward aligner + wavefront_aligner_t* wf_reverse; // Breakpoint Reverse aligner + wavefront_aligner_t* wf_base; // Base/Subsidiary aligner + // Operators + void (*wf_align_compute)(wavefront_aligner_t* const,const int); } wavefront_bialigner_t; /* @@ -69,6 +73,34 @@ void wavefront_bialigner_reap( void wavefront_bialigner_delete( wavefront_bialigner_t* const wf_bialigner); +/* + * Sequences + */ +void wavefront_bialigner_set_sequences_ascii( + wavefront_bialigner_t* const wf_bialigner, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length); +void wavefront_bialigner_set_sequences_lambda( + wavefront_bialigner_t* const wf_bialigner, + alignment_match_funct_t match_funct, + void* match_funct_arguments, + const int pattern_length, + const int text_length); +void wavefront_bialigner_set_sequences_packed2bits( + wavefront_bialigner_t* const wf_bialigner, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length); +void wavefront_bialigner_set_sequences_bounds( + wavefront_bialigner_t* const wf_bialigner, + const int pattern_begin, + const int pattern_end, + const int text_begin, + const int text_end); + /* * Accessors */ @@ -77,13 +109,9 @@ uint64_t wavefront_bialigner_get_size( void wavefront_bialigner_set_heuristic( wavefront_bialigner_t* const wf_bialigner, wavefront_heuristic_t* const heuristic); -void wavefront_bialigner_set_match_funct( +void wavefront_bialigner_set_max_alignment_steps( wavefront_bialigner_t* const wf_bialigner, - int (*match_funct)(int,int,void*), - void* const match_funct_arguments); -void wavefront_bialigner_set_max_alignment_score( - wavefront_bialigner_t* const wf_bialigner, - const int max_alignment_score); + const int max_alignment_steps); void wavefront_bialigner_set_max_memory( wavefront_bialigner_t* const wf_bialigner, const uint64_t max_memory_resident, @@ -92,6 +120,6 @@ void wavefront_bialigner_set_max_num_threads( wavefront_bialigner_t* const wf_bialigner, const int max_num_threads); void wavefront_bialigner_set_min_offsets_per_thread( - wavefront_bialigner_t* const wf_bialigner, - const int min_offsets_per_thread); + wavefront_bialigner_t* const wf_bialigner, + const int min_offsets_per_thread); #endif /* WAVEFRONT_BIALIGNER_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c index 8ba5ca33..7aff6007 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "system/mm_allocator.h" -#include "utils/string_padded.h" #include "alignment/affine2p_penalties.h" #include "wavefront_compute.h" @@ -128,9 +127,11 @@ bool wavefront_compute_endsfree_required( // Parameters alignment_form_t* const alg_form = &wf_aligner->alignment_form; wavefront_penalties_t* const penalties = &wf_aligner->penalties; - // Return is ends-free initialization is required + // Return if ends-free initialization is required if (penalties->match == 0) return false; if (alg_form->span != alignment_endsfree) return false; + if (alg_form->text_begin_free == 0 && + alg_form->pattern_begin_free == 0) return false; if (score % (-penalties->match) != 0) return false; // Ok return true; @@ -571,8 +572,9 @@ void wavefront_compute_trim_ends( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; wf_offset_t* const offsets = wavefront->offsets; // Trim from hi int k; @@ -651,3 +653,4 @@ void wavefront_compute_thread_limits( *thread_hi = t_hi; } #endif + diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c index d90390a9..c093a4e6 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "system/mm_allocator.h" -#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_backtrace_offload.h" @@ -48,8 +47,9 @@ void wavefront_compute_affine_idm( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -93,8 +93,9 @@ void wavefront_compute_affine_idm_piggyback( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -257,3 +258,5 @@ void wavefront_compute_affine( // Process wavefront ends wavefront_compute_process_ends(wf_aligner,&wavefront_set,score); } + + diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c index 2a1a3701..14b4bb1b 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_affine2p.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "system/mm_allocator.h" -#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_compute_affine.h" #include "wavefront_backtrace_offload.h" @@ -49,8 +48,9 @@ void wavefront_compute_affine2p_idm( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -113,8 +113,9 @@ void wavefront_compute_affine2p_idm_piggyback( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -365,3 +366,4 @@ void wavefront_compute_affine2p( // Process wavefront ends wavefront_compute_process_ends(wf_aligner,&wavefront_set,score); } + diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c index 1eedcfb9..13202a05 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_edit.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "system/mm_allocator.h" -#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_backtrace_offload.h" @@ -49,8 +48,9 @@ void wavefront_compute_indel_idm( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; const wf_offset_t* const prev_offsets = wf_prev->offsets; wf_offset_t* const curr_offsets = wf_curr->offsets; // Compute-Next kernel loop @@ -76,8 +76,9 @@ void wavefront_compute_edit_idm( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; const wf_offset_t* const prev_offsets = wf_prev->offsets; wf_offset_t* const curr_offsets = wf_curr->offsets; // Compute-Next kernel loop @@ -108,8 +109,9 @@ void wavefront_compute_indel_idm_piggyback( const int hi, const int score) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // Previous WF const wf_offset_t* const prev_offsets = wf_prev->offsets; const pcigar_t* const prev_pcigar = wf_prev->bt_pcigar; @@ -150,8 +152,9 @@ void wavefront_compute_edit_idm_piggyback( const int hi, const int score) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // Previous WF const wf_offset_t* const prev_offsets = wf_prev->offsets; const pcigar_t* const prev_pcigar = wf_prev->bt_pcigar; @@ -217,8 +220,9 @@ void wavefront_compute_edit_exact_prune( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront) { // Parameters - const int plen = wf_aligner->pattern_length; - const int tlen = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int plen = sequences->pattern_length; + const int tlen = sequences->text_length; wf_offset_t* const offsets = wavefront->offsets; const int lo = wavefront->lo; const int hi = wavefront->hi; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c index 3206fbf7..d9c1aa7b 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_compute_linear.c @@ -31,7 +31,6 @@ #include "utils/commons.h" #include "system/mm_allocator.h" -#include "utils/string_padded.h" #include "wavefront_compute.h" #include "wavefront_backtrace_offload.h" @@ -48,8 +47,9 @@ void wavefront_compute_linear_idm( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // In Offsets const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const wf_offset_t* const m_open1 = wavefront_set->in_mwavefront_open1->offsets; @@ -81,8 +81,9 @@ void wavefront_compute_linear_idm_piggyback( const int lo, const int hi) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // In M const wf_offset_t* const m_misms = wavefront_set->in_mwavefront_misms->offsets; const pcigar_t* const m_misms_bt_pcigar = wavefront_set->in_mwavefront_misms->bt_pcigar; @@ -192,3 +193,5 @@ void wavefront_compute_linear( // Process wavefront ends wavefront_compute_process_ends(wf_aligner,&wavefront_set,score); } + + diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c index 41425a8d..c14068a9 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.c @@ -41,13 +41,12 @@ bool wavefront_check_alignment( FILE* const stream, wavefront_aligner_t* const wf_aligner) { // Parameters - const char* const pattern = wf_aligner->pattern; - const int pattern_length = wf_aligner->pattern_length; - const char* const text = wf_aligner->text; - const int text_length = wf_aligner->text_length; - // Custom function to compare sequences - alignment_match_funct_t match_funct = wf_aligner->match_funct; - void* match_funct_arguments = wf_aligner->match_funct_arguments; + wavefront_sequences_t* const sequences = (wf_aligner->bialigner==NULL) ? + &wf_aligner->sequences : &wf_aligner->bialigner->wf_forward->sequences; + const char* const pattern = sequences->pattern_buffer; + const int pattern_length = sequences->pattern_buffer_length; + const char* const text = sequences->text_buffer; + const int text_length = sequences->text_buffer_length; // CIGAR cigar_t* const cigar = wf_aligner->cigar; char* const operations = cigar->operations; @@ -60,14 +59,15 @@ bool wavefront_check_alignment( switch (operations[i]) { case 'M': { // Check match - const bool is_match = (match_funct!=NULL) ? - match_funct(pattern_pos,text_pos,match_funct_arguments) : - pattern[pattern_pos] == text[text_pos]; - if (!is_match) { - fprintf(stream,"[WFA::Check] Alignment not matching (pattern[%d]=%c != text[%d]=%c)\n", - pattern_pos,pattern[pattern_pos],text_pos,text[text_pos]); - alignment_correct = false; - break; + if (sequences->mode != wf_sequences_lambda) { + const bool is_match = (pattern[pattern_pos]==text[text_pos]); + if (!is_match) { + fprintf(stream,"[WFA::Check] Alignment not matching (pattern[%d]=%c != text[%d]=%c)\n", + pattern_pos,pattern[pattern_pos], + text_pos,text[text_pos]); + alignment_correct = false; + break; + } } ++pattern_pos; ++text_pos; @@ -75,14 +75,15 @@ bool wavefront_check_alignment( } case 'X': { // Check mismatch - const bool is_match = (match_funct!=NULL) ? - match_funct(pattern_pos,text_pos,match_funct_arguments) : - pattern[pattern_pos] == text[text_pos]; - if (is_match) { - fprintf(stream,"[WFA::Check] Alignment not mismatching (pattern[%d]=%c == text[%d]=%c)\n", - pattern_pos,pattern[pattern_pos],text_pos,text[text_pos]); - alignment_correct = false; - break; + if (sequences->mode != wf_sequences_lambda) { + const bool is_match = (pattern[pattern_pos]==text[text_pos]); + if (is_match) { + fprintf(stream,"[WFA::Check] Alignment not mismatching (pattern[%d]=%c == text[%d]=%c)\n", + pattern_pos,pattern[pattern_pos], + text_pos,text[text_pos]); + alignment_correct = false; + break; + } } ++pattern_pos; ++text_pos; @@ -121,124 +122,101 @@ bool wavefront_check_alignment( */ void wavefront_report_lite( FILE* const stream, - wavefront_aligner_t* const wf_aligner) { + wavefront_aligner_t* const wf_aligner, + const bool alignment_completed) { // Parameters - const char* const pattern = wf_aligner->pattern; - const int pattern_length = wf_aligner->pattern_length; - const char* const text = wf_aligner->text; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = (wf_aligner->bialigner==NULL) ? + &wf_aligner->sequences : &wf_aligner->bialigner->wf_forward->sequences; + const char* const pattern = sequences->pattern; + const int pattern_length = sequences->pattern_length; + const char* const text = sequences->text; + const int text_length = sequences->text_length; const int status = wf_aligner->align_status.status; const uint64_t memory_used = wf_aligner->align_status.memory_used; - // Banner - fprintf(stream,"[WFA::Debug]"); - // Sequences - const int score = wavefront_compute_classic_score( - wf_aligner,wf_aligner->pattern_length, - wf_aligner->text_length,wf_aligner->cigar->score); - fprintf(stream,"\t%d",score); - fprintf(stream,"\t%d\t%d",pattern_length,text_length); - fprintf(stream,"\t%s",(status==0) ? "OK" : "FAIL"); - fprintf(stream,"\t%2.3f",TIMER_GET_TOTAL_MS(&wf_aligner->system.timer)); - fprintf(stream,"\t%luMB\t",CONVERT_B_TO_MB(memory_used)); - fprintf(stream,"["); - wavefront_aligner_print_type(stream,wf_aligner); - fprintf(stream,","); - wavefront_aligner_print_scope(stream,wf_aligner); - fprintf(stream,","); - wavefront_penalties_print(stream,&wf_aligner->penalties); - fprintf(stream,"]\t"); - cigar_print(stream,wf_aligner->cigar,true); - if (wf_aligner->match_funct != NULL) { - fprintf(stream,"\t-\t-"); + // BANNER (#0) + if (alignment_completed) { + fprintf(stream,"[WFA::Debug]"); } else { - fprintf(stream,"\t%.*s\t%.*s",pattern_length,pattern,text_length,text); + fprintf(stream,"[WFA::Debug::BEGIN]"); } - fprintf(stream,"\n"); -} -void wavefront_report_verbose_begin( - FILE* const stream, - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length) { - // Input sequences - fprintf(stream,"[WFA::Report::Begin] ["); - wavefront_aligner_print_type(stream,wf_aligner); - fprintf(stream,"]-Alignment (obj=%p)\n",wf_aligner); - if (wf_aligner->match_funct != NULL) { - fprintf(stream,"[WFA::Report]\tPattern\t%d\tcustom-funct()\n",pattern_length); - fprintf(stream,"[WFA::Report]\tText\t%d\tcustom-funct()\n",text_length); + // SCORE (#1) + // const int score = wavefront_compute_classic_score( + // wf_aligner,pattern_length,text_length,wf_aligner->cigar->score); + const int score = wf_aligner->cigar->score; + if (alignment_completed && score!=INT32_MIN) { + fprintf(stream,"\t%d",score); + } else { + fprintf(stream,"\t*"); + } + // PATTERN_LENGTH (#2) + fprintf(stream,"\t%d",pattern_length); + // TEXT_LENGTH (#3) + fprintf(stream,"\t%d",text_length); + // STATUS (#4) + fprintf(stream,"\t%s",wavefront_align_strerror_short(status)); + // TIME (#5) + if (alignment_completed) { + fprintf(stream,"\t%2.3f",TIMER_GET_TOTAL_MS(&wf_aligner->system.timer)); + } else { + fprintf(stream,"\t-"); + } + // MEMORY (#6) + if (alignment_completed) { + fprintf(stream,"\t%luMB\t",CONVERT_B_TO_MB(memory_used)); } else { - fprintf(stream,"[WFA::Report]\tPattern\t%d\t%.*s\n",pattern_length,pattern_length,pattern); - fprintf(stream,"[WFA::Report]\tText\t%d\t%.*s\n",text_length,text_length,text); + fprintf(stream,"\t-\t"); } - // Alignment scope/form - fprintf(stream,"[WFA::Report]\tScope="); + // ATTRIBUTES (#7) + fprintf(stream,"["); + wavefront_aligner_print_mode(stream,wf_aligner); + fprintf(stream,";"); wavefront_aligner_print_scope(stream,wf_aligner); - fprintf(stream," Max-score=%d", - wf_aligner->system.max_alignment_score); - // Penalties - fprintf(stream," Penalties="); + fprintf(stream,";"); wavefront_penalties_print(stream,&wf_aligner->penalties); - // Heuristic - fprintf(stream," Heuristic="); + fprintf(stream,";"); + wavefront_aligner_print_conf(stream,wf_aligner); + fprintf(stream,";"); wavefront_heuristic_print(stream,&wf_aligner->heuristic); - // Memory mode - fprintf(stream," Memory.mode=(%d,%luMB,%luMB,%luMB)\n", - wf_aligner->memory_mode, - CONVERT_B_TO_MB(wf_aligner->system.max_memory_compact), - CONVERT_B_TO_MB(wf_aligner->system.max_memory_resident), - CONVERT_B_TO_MB(wf_aligner->system.max_memory_abort)); -} -void wavefront_report_verbose_end( - FILE* const stream, - wavefront_aligner_t* const wf_aligner) { - // Finish report - fprintf(stream,"[WFA::Report::End]\tFinish.status=%d",wf_aligner->align_status.status); - fprintf(stream," Time.taken="); - timer_print_total(stream,&wf_aligner->system.timer); - fprintf(stream," Memory.used=%luMB", - CONVERT_B_TO_MB(wf_aligner->align_status.memory_used)); - fprintf(stream," WFA.components=(wfs=%d,maxlo=%d,maxhi=%d)", + fprintf(stream,";"); + fprintf(stream,"(%d,%d,%d)", wf_aligner->wf_components.num_wavefronts, wf_aligner->wf_components.historic_min_lo, wf_aligner->wf_components.historic_max_hi); - const int score = wavefront_compute_classic_score( - wf_aligner,wf_aligner->pattern_length, - wf_aligner->text_length,wf_aligner->cigar->score); - fprintf(stream," WFA.score=%d",score); - fprintf(stream," WFA.cigar="); - cigar_print(stream,wf_aligner->cigar,true); + fprintf(stream,"]\t"); + // CIGAR (#8) + if (!alignment_completed || cigar_is_null(wf_aligner->cigar)) { + fprintf(stream,"-"); + } else { + cigar_print(stream,wf_aligner->cigar,true); + } + // SEQUENCES (#9 #10) + if (sequences->mode == wf_sequences_lambda) { + fprintf(stream,"\t-\t-"); + } else { + fprintf(stream,"\t%.*s\t%.*s",pattern_length,pattern,text_length,text); + } fprintf(stream,"\n"); } /* * Debug */ -void wavefront_debug_prologue( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length) { +void wavefront_debug_begin( + wavefront_aligner_t* const wf_aligner) { // Check verbose level if (wf_aligner->system.verbose >= 1) { + timer_reset(&wf_aligner->system.timer); timer_start(&wf_aligner->system.timer); if (wf_aligner->system.verbose >= 4) { - wavefront_report_verbose_begin(stderr,wf_aligner, - pattern,pattern_length,text,text_length); + wavefront_report_lite(stderr,wf_aligner,false); } } } -void wavefront_debug_epilogue( +void wavefront_debug_end( wavefront_aligner_t* const wf_aligner) { // Print Summary if (wf_aligner->system.verbose >= 1) { timer_stop(&wf_aligner->system.timer); - if (wf_aligner->system.verbose >= 4) { - wavefront_report_verbose_end(stderr,wf_aligner); - } - wavefront_report_lite(stderr,wf_aligner); + wavefront_report_lite(stderr,wf_aligner,true); } } /* @@ -248,7 +226,7 @@ void wavefront_debug_check_correct( wavefront_aligner_t* const wf_aligner) { // Check correct if (wf_aligner->system.check_alignment_correct && - wf_aligner->align_status.status == WF_STATUS_SUCCESSFUL && + wf_aligner->align_status.status == WF_STATUS_ALG_COMPLETED && wf_aligner->alignment_scope == compute_alignment) { if (!wavefront_check_alignment(stderr,wf_aligner)) { fprintf(stderr,"[WFA::Check] Error: Alignment incorrect\n"); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h index 1bdb8532..828343af 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_debug.h @@ -37,13 +37,9 @@ /* * Debug */ -void wavefront_debug_prologue( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length); -void wavefront_debug_epilogue( +void wavefront_debug_begin( + wavefront_aligner_t* const wf_aligner); +void wavefront_debug_end( wavefront_aligner_t* const wf_aligner); /* diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c index 945f278b..1ba78866 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.c @@ -26,376 +26,177 @@ * * PROJECT: Wavefront Alignment Algorithms * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches + * DESCRIPTION: WFA module for the "extension" of exact matches */ #include "utils/commons.h" #include "system/mm_allocator.h" -#include "utils/string_padded.h" #include "wavefront_extend.h" -#include "wavefront_align.h" +#include "wavefront_extend_kernels.h" +#include "wavefront_extend_kernels_avx.h" #include "wavefront_compute.h" -#include "wavefront_heuristic.h" +#include "wavefront_termination.h" #ifdef WFA_PARALLEL #include #endif /* - * Termination (detect end of alignment) + * Wavefront Extension (End-to-end) */ -bool wavefront_extend_end2end_check_termination( +void wavefront_extend_end2end_dispatcher_seq( wavefront_aligner_t* const wf_aligner, wavefront_t* const mwavefront, const int score, - const int score_mod) { - // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; - const affine2p_matrix_type component_end = wf_aligner->component_end; - const int alignment_k = DPMATRIX_DIAGONAL(text_length,pattern_length); - const wf_offset_t alignment_offset = DPMATRIX_OFFSET(text_length,pattern_length); - // Select end component - switch (component_end) { - case affine2p_matrix_M: { - // Check diagonal/offset - if (mwavefront->lo > alignment_k || alignment_k > mwavefront->hi) return false; // Not done - const wf_offset_t moffset = mwavefront->offsets[alignment_k]; - if (moffset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_I1: { - // Fetch I1-wavefront & check diagonal/offset - wavefront_t* const i1wavefront = wf_aligner->wf_components.i1wavefronts[score_mod]; - if (i1wavefront == NULL || i1wavefront->lo > alignment_k || alignment_k > i1wavefront->hi) return false; // Not done - const wf_offset_t i1offset = i1wavefront->offsets[alignment_k]; - if (i1offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_I2: { - // Fetch I2-wavefront & check diagonal/offset - wavefront_t* const i2wavefront = wf_aligner->wf_components.i2wavefronts[score_mod]; - if (i2wavefront == NULL || i2wavefront->lo > alignment_k || alignment_k > i2wavefront->hi) return false; // Not done - const wf_offset_t i2offset = i2wavefront->offsets[alignment_k]; - if (i2offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_D1: { - // Fetch D1-wavefront & check diagonal/offset - wavefront_t* const d1wavefront = wf_aligner->wf_components.d1wavefronts[score_mod]; - if (d1wavefront == NULL || d1wavefront->lo > alignment_k || alignment_k > d1wavefront->hi) return false; // Not done - const wf_offset_t d1offset = d1wavefront->offsets[alignment_k]; - if (d1offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - case affine2p_matrix_D2: { - // Fetch D2-wavefront & check diagonal/offset - wavefront_t* const d2wavefront = wf_aligner->wf_components.d2wavefronts[score_mod]; - if (d2wavefront == NULL || d2wavefront->lo > alignment_k || alignment_k > d2wavefront->hi) return false; // Not done - const wf_offset_t d2offset = d2wavefront->offsets[alignment_k]; - if (d2offset < alignment_offset) return false; // Not done - // We are done - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = alignment_k; - wf_aligner->alignment_end_pos.offset = alignment_offset; - return true; - } - default: - break; - } - return false; -} -bool wavefront_extend_endsfree_check_termination( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int k, - const wf_offset_t offset) { - // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; - // Check ends-free reaching boundaries - const int h_pos = WAVEFRONT_H(k,offset); - const int v_pos = WAVEFRONT_V(k,offset); - if (h_pos >= text_length) { // Text is aligned - // Is Pattern end-free? - const int pattern_left = pattern_length - v_pos; - const int pattern_end_free = wf_aligner->alignment_form.pattern_end_free; - if (pattern_left <= pattern_end_free) { - #ifdef WFA_PARALLEL - #pragma omp critical - #endif - { - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = k; - wf_aligner->alignment_end_pos.offset = offset; - } - return true; // Quit (we are done) - } - } - if (v_pos >= pattern_length) { // Pattern is aligned - // Is text end-free? - const int text_left = text_length - h_pos; - const int text_end_free = wf_aligner->alignment_form.text_end_free; - if (text_left <= text_end_free) { - #ifdef WFA_PARALLEL - #pragma omp critical - #endif - { - wf_aligner->alignment_end_pos.score = score; - wf_aligner->alignment_end_pos.k = k; - wf_aligner->alignment_end_pos.offset = offset; - } - return true; // Quit (we are done) - } - } - // Not done - return false; -} -/* - * Extend kernel - */ -FORCE_INLINE wf_offset_t wavefront_extend_matches_packed_kernel( - wavefront_aligner_t* const wf_aligner, - const int k, - wf_offset_t offset) { - // Fetch pattern/text blocks - uint64_t* pattern_blocks = (uint64_t*)(wf_aligner->pattern+WAVEFRONT_V(k,offset)); - uint64_t* text_blocks = (uint64_t*)(wf_aligner->text+WAVEFRONT_H(k,offset)); - // Compare 64-bits blocks - uint64_t cmp = *pattern_blocks ^ *text_blocks; - while (__builtin_expect(cmp==0,0)) { - // Increment offset (full block) - offset += 8; - // Next blocks - ++pattern_blocks; - ++text_blocks; - // Compare - cmp = *pattern_blocks ^ *text_blocks; - } - // Count equal characters - const int equal_right_bits = __builtin_ctzl(cmp); - const int equal_chars = DIV_FLOOR(equal_right_bits,8); - offset += equal_chars; - // Return extended offset - return offset; -} -/* - * Wavefront offset extension comparing characters - * Remember: - * - No offset is out of boundaries !(h>tlen,v>plen) - * - if (h==tlen,v==plen) extension won't increment (sentinels) - */ -FORCE_NO_INLINE void wavefront_extend_matches_packed_end2end( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, const int lo, const int hi) { - wf_offset_t* const offsets = mwavefront->offsets; - int k; - for (k=lo;k<=hi;++k) { - // Fetch offset - const wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Extend offset - offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); - } -} -FORCE_NO_INLINE wf_offset_t wavefront_extend_matches_packed_max( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int lo, - const int hi) { - wf_offset_t* const offsets = mwavefront->offsets; - wf_offset_t max_antidiag = 0; - int k; - for (k=lo;k<=hi;++k) { - // Fetch offset - const wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Extend offset - offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); - // Compute max - const wf_offset_t antidiag = WAVEFRONT_ANTIDIAGONAL(k,offsets[k]); - if (max_antidiag < antidiag) max_antidiag = antidiag; - } - return max_antidiag; -} -FORCE_NO_INLINE bool wavefront_extend_matches_packed_endsfree( - wavefront_aligner_t* const wf_aligner, - wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi) { - wf_offset_t* const offsets = mwavefront->offsets; - int k; - for (k=lo;k<=hi;++k) { - // Fetch offset - wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Extend offset - offset = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); - offsets[k] = offset; - // Check ends-free reaching boundaries - if (wavefront_extend_endsfree_check_termination(wf_aligner,mwavefront,score,k,offset)) { - return true; // Quit (we are done) - } + // Parameters + wavefront_sequences_t* const seqs = &wf_aligner->sequences; + // Check the sequence mode + if (seqs->mode == wf_sequences_ascii) { +//#if __AVX2__ // TODO +// wavefront_extend_matches_packed_end2end_avx2(wf_aligner,mwavefront,lo,hi); +//#else + wavefront_extend_matches_packed_end2end(wf_aligner,mwavefront,lo,hi); +//#endif + } else { + wf_offset_t dummy; + wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,false,&dummy); } - // Alignment not finished - return false; } -bool wavefront_extend_matches_custom( +void wavefront_extend_end2end_dispatcher_threads( wavefront_aligner_t* const wf_aligner, wavefront_t* const mwavefront, - const int score, - const int lo, - const int hi, - const bool endsfree) { - // Parameters (custom matching function) - alignment_match_funct_t match_funct = wf_aligner->match_funct; - void* const func_arguments = wf_aligner->match_funct_arguments; - // Extend diagonally each wavefront point - wf_offset_t* const offsets = mwavefront->offsets; - int k; - for (k=lo;k<=hi;++k) { - // Check offset - wf_offset_t offset = offsets[k]; - if (offset == WAVEFRONT_OFFSET_NULL) continue; - // Count equal characters - int v = WAVEFRONT_V(k,offset); - int h = WAVEFRONT_H(k,offset); - while (match_funct(v,h,func_arguments)) { - h++; v++; offset++; - } - // Update offset - offsets[k] = offset; - // Check ends-free reaching boundaries - if (endsfree && wavefront_extend_endsfree_check_termination(wf_aligner,mwavefront,score,k,offset)) { - return true; // Quit (we are done) + const int score) { + // Parameters + const int lo = mwavefront->lo; + const int hi = mwavefront->hi; + const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); + if (num_threads == 1) { + // Extend wavefront single-thread + wavefront_extend_end2end_dispatcher_seq(wf_aligner,mwavefront,score,lo,hi); + } else { +#ifdef WFA_PARALLEL + // Extend wavefront in parallel + #pragma omp parallel num_threads(num_threads) + { + int t_lo, t_hi; + wavefront_compute_thread_limits(omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + wavefront_extend_end2end_dispatcher_seq(wf_aligner,mwavefront,score,t_lo,t_hi); } +#endif } - // Alignment not finished - return false; } -/* - * Wavefront exact "extension" - */ -int wavefront_extend_end2end_max( +int wavefront_extend_end2end( wavefront_aligner_t* const wf_aligner, - const int score, - int* const max_antidiagonal) { + const int score) { // Compute score const bool memory_modular = wf_aligner->wf_components.memory_modular; const int max_score_scope = wf_aligner->wf_components.max_score_scope; const int score_mod = (memory_modular) ? score % max_score_scope : score; - *max_antidiagonal = 0; // Init // Fetch m-wavefront wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; if (mwavefront == NULL) { // Check alignment feasibility (for heuristic variants that can lead to no solution) if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { - wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; + wf_aligner->align_status.status = WF_STATUS_END_UNREACHABLE; wf_aligner->align_status.score = score; return 1; // Done } return 0; // Not done } - // Multithreading dispatcher + // Extend (dispatcher) + wavefront_extend_end2end_dispatcher_threads(wf_aligner,mwavefront,score); + const bool end_reached = wavefront_termination_end2end(wf_aligner,mwavefront,score,score_mod); + if (end_reached) { + wf_aligner->align_status.status = WF_STATUS_END_REACHED; + wf_aligner->align_status.score = score; + return 1; // Done + } + // Cut-off wavefront heuristically + if (wf_aligner->heuristic.strategy != wf_heuristic_none) { + if (wavefront_heuristic_cufoff(wf_aligner,score,score_mod)) { + wf_aligner->align_status.status = WF_STATUS_END_UNREACHABLE; + wf_aligner->align_status.score = score; + return 1; // Done + } + } + return 0; // Not done +} +/* + * Wavefront Extension (End-to-end + MAX-antidiagonal) + */ +wf_offset_t wavefront_extend_end2end_max_dispatcher_seq( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi) { + // Parameters + wavefront_sequences_t* const seqs = &wf_aligner->sequences; + // Check the sequence mode + if (seqs->mode == wf_sequences_ascii) { + return wavefront_extend_matches_packed_end2end_max(wf_aligner,mwavefront,lo,hi); + } else { + wf_offset_t max_antidiag; + wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,false,&max_antidiag); + return max_antidiag; + } +} +wf_offset_t wavefront_extend_end2end_max_dispatcher_threads( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score) { + // Parameters const int lo = mwavefront->lo; const int hi = mwavefront->hi; wf_offset_t max_antidiag = 0; + // Select number of threads const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); if (num_threads == 1) { - // Extend wavefront - max_antidiag = wavefront_extend_matches_packed_max(wf_aligner,mwavefront,lo,hi); + // Extend wavefront single-thread + max_antidiag = wavefront_extend_end2end_max_dispatcher_seq(wf_aligner,mwavefront,score,lo,hi); } else { -#ifdef WFA_PARALLEL // Extend wavefront in parallel +#ifdef WFA_PARALLEL #pragma omp parallel num_threads(num_threads) { int t_lo, t_hi; - wavefront_compute_thread_limits( - omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - wf_offset_t t_max_antidiag = wavefront_extend_matches_packed_max(wf_aligner,mwavefront,t_lo,t_hi); - #ifdef WFA_PARALLEL + wavefront_compute_thread_limits(omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + wf_offset_t t_max_antidiag = wavefront_extend_end2end_max_dispatcher_seq(wf_aligner,mwavefront,score,t_lo,t_hi); #pragma omp critical - #endif { if (t_max_antidiag > max_antidiag) max_antidiag = t_max_antidiag; } } #endif } - // Check end-to-end finished - const bool end_reached = wavefront_extend_end2end_check_termination(wf_aligner,mwavefront,score,score_mod); - if (end_reached) { - wf_aligner->align_status.status = WF_STATUS_END_REACHED; - wf_aligner->align_status.score = score; - return 1; // Done - } - // Cut-off wavefront heuristically - if (wf_aligner->heuristic.strategy != wf_heuristic_none) { - wavefront_heuristic_cufoff(wf_aligner,score,score_mod); - } - *max_antidiagonal = max_antidiag; - return 0; // Not done + // Return maximum antidiagonal + return max_antidiag; } -int wavefront_extend_end2end( +int wavefront_extend_end2end_max( wavefront_aligner_t* const wf_aligner, - const int score) { + const int score, + int* const max_antidiagonal) { // Compute score const bool memory_modular = wf_aligner->wf_components.memory_modular; const int max_score_scope = wf_aligner->wf_components.max_score_scope; const int score_mod = (memory_modular) ? score % max_score_scope : score; + *max_antidiagonal = 0; // Init // Fetch m-wavefront wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; if (mwavefront == NULL) { - // Check alignment feasibility (for heuristic variants that can lead to no solution) + // Check alignment feasibility (heuristic variants that can lead to no solution) if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { - wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; + wf_aligner->align_status.status = WF_STATUS_END_UNREACHABLE; wf_aligner->align_status.score = score; return 1; // Done } return 0; // Not done } - // Multithreading dispatcher - const int lo = mwavefront->lo; - const int hi = mwavefront->hi; - bool end_reached = false; - const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); - if (num_threads == 1) { - // Extend wavefront - wavefront_extend_matches_packed_end2end(wf_aligner,mwavefront,lo,hi); - } else { -#ifdef WFA_PARALLEL - // Extend wavefront in parallel - #pragma omp parallel num_threads(num_threads) - { - int t_lo, t_hi; - wavefront_compute_thread_limits( - omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - wavefront_extend_matches_packed_end2end(wf_aligner,mwavefront,t_lo,t_hi); - } -#endif - } - // Check end-to-end finished - end_reached = wavefront_extend_end2end_check_termination(wf_aligner,mwavefront,score,score_mod); + // Extend (dispatcher) + const wf_offset_t max_ak = wavefront_extend_end2end_max_dispatcher_threads(wf_aligner,mwavefront,score); + const bool end_reached = wavefront_termination_end2end(wf_aligner,mwavefront,score,score_mod); if (end_reached) { wf_aligner->align_status.status = WF_STATUS_END_REACHED; wf_aligner->align_status.score = score; @@ -403,106 +204,82 @@ int wavefront_extend_end2end( } // Cut-off wavefront heuristically if (wf_aligner->heuristic.strategy != wf_heuristic_none) { - wavefront_heuristic_cufoff(wf_aligner,score,score_mod); + if (wavefront_heuristic_cufoff(wf_aligner,score,score_mod)) { + wf_aligner->align_status.status = WF_STATUS_END_UNREACHABLE; + wf_aligner->align_status.score = score; + return 1; // Done + } } + *max_antidiagonal = max_ak; return 0; // Not done } -int wavefront_extend_endsfree( +/* + * Wavefront Extension (Ends-free) + */ +bool wavefront_extend_endsfree_dispatcher_seq( wavefront_aligner_t* const wf_aligner, - const int score) { - // Modular wavefront - const bool memory_modular = wf_aligner->wf_components.memory_modular; - const int max_score_scope = wf_aligner->wf_components.max_score_scope; - const int score_mod = (memory_modular) ? score % max_score_scope : score; - // Fetch m-wavefront - wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; - if (mwavefront == NULL) { - // Check alignment feasibility (for heuristic variants that can lead to no solution) - if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { - wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; - wf_aligner->align_status.score = score; - return 1; // Done - } - return 0; // Not done + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi) { + // Parameters + wavefront_sequences_t* const seqs = &wf_aligner->sequences; + // Check the sequence mode + if (seqs->mode == wf_sequences_ascii) { + return wavefront_extend_matches_packed_endsfree(wf_aligner,mwavefront,score,lo,hi); + } else { + wf_offset_t dummy; + return wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,true,&dummy); } - // Multithreading dispatcher +} +bool wavefront_extend_endsfree_dispatcher_threads( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score) { + // Parameters const int lo = mwavefront->lo; const int hi = mwavefront->hi; bool end_reached = false; const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); if (num_threads == 1) { - // Extend wavefront - end_reached = wavefront_extend_matches_packed_endsfree(wf_aligner,mwavefront,score,lo,hi); + // Extend wavefront single-thread + end_reached = wavefront_extend_endsfree_dispatcher_seq(wf_aligner,mwavefront,score,lo,hi); } else { #ifdef WFA_PARALLEL // Extend wavefront in parallel #pragma omp parallel num_threads(num_threads) { int t_lo, t_hi; - wavefront_compute_thread_limits( - omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - if (wavefront_extend_matches_packed_endsfree(wf_aligner,mwavefront,score,t_lo,t_hi)) { + wavefront_compute_thread_limits(omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); + if (wavefront_extend_endsfree_dispatcher_seq(wf_aligner,mwavefront,score,t_lo,t_hi)) { end_reached = true; } } #endif } - if (end_reached) { - wf_aligner->align_status.status = WF_STATUS_END_REACHED; - wf_aligner->align_status.score = score; - return 1; // Done - } - // Cut-off wavefront heuristically - if (wf_aligner->heuristic.strategy != wf_heuristic_none) { - wavefront_heuristic_cufoff(wf_aligner,score,score_mod); - } - return 0; // Not done + // Return end-reached + return end_reached; } -int wavefront_extend_custom( +int wavefront_extend_endsfree( wavefront_aligner_t* const wf_aligner, const int score) { - // Compute score + // Modular wavefront const bool memory_modular = wf_aligner->wf_components.memory_modular; const int max_score_scope = wf_aligner->wf_components.max_score_scope; const int score_mod = (memory_modular) ? score % max_score_scope : score; // Fetch m-wavefront wavefront_t* const mwavefront = wf_aligner->wf_components.mwavefronts[score_mod]; if (mwavefront == NULL) { - // Check alignment feasibility (for heuristic variants that can lead to no solution) + // Check alignment feasibility (heuristic variants that can lead to no solution) if (wf_aligner->align_status.num_null_steps > wf_aligner->wf_components.max_score_scope) { - wf_aligner->align_status.status = WF_STATUS_UNFEASIBLE; + wf_aligner->align_status.status = WF_STATUS_END_UNREACHABLE; wf_aligner->align_status.score = score; return 1; // Done } return 0; // Not done } - // Multithreading dispatcher - const bool endsfree = (wf_aligner->alignment_form.span == alignment_endsfree); - const int lo = mwavefront->lo; - const int hi = mwavefront->hi; - bool end_reached = false; - const int num_threads = wavefront_compute_num_threads(wf_aligner,lo,hi); - if (num_threads == 1) { - // Extend wavefront - end_reached = wavefront_extend_matches_custom(wf_aligner,mwavefront,score,lo,hi,endsfree); - } else { -#ifdef WFA_PARALLEL - // Extend wavefront in parallel - #pragma omp parallel num_threads(num_threads) - { - int t_lo, t_hi; - wavefront_compute_thread_limits( - omp_get_thread_num(),omp_get_num_threads(),lo,hi,&t_lo,&t_hi); - if (wavefront_extend_matches_custom(wf_aligner,mwavefront,score,t_lo,t_hi,endsfree)) { - end_reached = true; - } - } -#endif - } - // Check end-to-end finished - if (!endsfree) { - end_reached = wavefront_extend_end2end_check_termination(wf_aligner,mwavefront,score,score_mod); - } + // Extend (dispatcher) + const bool end_reached = wavefront_extend_endsfree_dispatcher_threads(wf_aligner,mwavefront,score); if (end_reached) { wf_aligner->align_status.status = WF_STATUS_END_REACHED; wf_aligner->align_status.score = score; @@ -510,7 +287,11 @@ int wavefront_extend_custom( } // Cut-off wavefront heuristically if (wf_aligner->heuristic.strategy != wf_heuristic_none) { - wavefront_heuristic_cufoff(wf_aligner,score,score_mod); + if (wavefront_heuristic_cufoff(wf_aligner,score,score_mod)) { + wf_aligner->align_status.status = WF_STATUS_END_UNREACHABLE; + wf_aligner->align_status.score = score; + return 1; // Done + } } return 0; // Not done } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h index 93455896..d79d2ff2 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend.h @@ -26,7 +26,7 @@ * * PROJECT: Wavefront Alignment Algorithms * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches + * DESCRIPTION: WFA module for the "extension" of exact matches */ #ifndef WAVEFRONT_EXTEND_H_ @@ -35,7 +35,7 @@ #include "wavefront_aligner.h" /* - * Wavefront exact "extension" + * Wavefront extension */ int wavefront_extend_end2end( wavefront_aligner_t* const wf_aligner, @@ -44,11 +44,9 @@ int wavefront_extend_end2end_max( wavefront_aligner_t* const wf_aligner, const int score, int* const max_antidiagonal); + int wavefront_extend_endsfree( wavefront_aligner_t* const wf_aligner, const int score); -int wavefront_extend_custom( - wavefront_aligner_t* const wf_aligner, - const int score); #endif /* WAVEFRONT_EXTEND_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c new file mode 100644 index 00000000..fe478693 --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.c @@ -0,0 +1,177 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WFA module for the "extension" of exact matches + */ + +#include "wavefront_extend_kernels.h" +#include "wavefront_termination.h" + +/* + * Inner-most extend kernel (blockwise comparisons) + */ +FORCE_INLINE wf_offset_t wavefront_extend_matches_packed_kernel( + wavefront_aligner_t* const wf_aligner, + const int k, + wf_offset_t offset) { + // Fetch pattern/text blocks + uint64_t* pattern_blocks = (uint64_t*)(wf_aligner->sequences.pattern+WAVEFRONT_V(k,offset)); + uint64_t* text_blocks = (uint64_t*)(wf_aligner->sequences.text+WAVEFRONT_H(k,offset)); + // Compare 64-bits blocks + uint64_t cmp = *pattern_blocks ^ *text_blocks; + while (__builtin_expect(cmp==0,0)) { + // Increment offset (full block) + offset += 8; + // Next blocks + ++pattern_blocks; + ++text_blocks; + // Compare + cmp = *pattern_blocks ^ *text_blocks; + } + // Count equal characters + const int equal_right_bits = __builtin_ctzl(cmp); + const int equal_chars = DIV_FLOOR(equal_right_bits,8); + offset += equal_chars; + // Return extended offset + return offset; +} +/* + * Wavefront-Extend Inner Kernels + * Wavefront offset extension comparing characters + * Remember: + * - No offset is out of boundaries !(h>tlen,v>plen) + * - if (h==tlen,v==plen) extension won't increment (sentinels) + */ +FORCE_NO_INLINE void wavefront_extend_matches_packed_end2end( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi) { + wf_offset_t* const offsets = mwavefront->offsets; + int k; + for (k=lo;k<=hi;++k) { + // Fetch offset + const wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Extend offset + offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); + } +} +FORCE_NO_INLINE wf_offset_t wavefront_extend_matches_packed_end2end_max( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi) { + wf_offset_t* const offsets = mwavefront->offsets; + wf_offset_t max_antidiag = 0; + int k; + for (k=lo;k<=hi;++k) { + // Fetch offset + const wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Extend offset + offsets[k] = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); + // Compute max + const wf_offset_t antidiag = WAVEFRONT_ANTIDIAGONAL(k,offsets[k]); + if (max_antidiag < antidiag) max_antidiag = antidiag; + } + return max_antidiag; +} +FORCE_NO_INLINE bool wavefront_extend_matches_packed_endsfree( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi) { + // Parameters + wf_offset_t* const offsets = mwavefront->offsets; + int k; + for (k=lo;k<=hi;++k) { + // Fetch offset + wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Extend offset + offset = wavefront_extend_matches_packed_kernel(wf_aligner,k,offset); + offsets[k] = offset; + // Check ends-free reaching boundaries + if (wavefront_termination_endsfree(wf_aligner,mwavefront,score,k,offset)) { + return true; // Quit (we are done) + } + /* + * TODO + const int h_pos = WAVEFRONT_H(k,offset); + const int v_pos = WAVEFRONT_V(k,offset); + if (h_pos >= text_length || v_pos >= pattern_length) { // FIXME Use wherever necessary + if (wavefront_extend_endsfree_check_termination(wf_aligner,mwavefront,score,k,offset)) { + return true; // Quit (we are done) + } + */ + } + // Alignment not finished + return false; +} +/* + * Wavefront-Extend Inner Kernel (Custom match function) + */ +bool wavefront_extend_matches_custom( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi, + const bool endsfree, + wf_offset_t* const max_antidiag) { + // Parameters + wavefront_sequences_t* const seqs = &wf_aligner->sequences; + // Extend diagonally each wavefront point + wf_offset_t* const offsets = mwavefront->offsets; + *max_antidiag = 0; + int k; + for (k=lo;k<=hi;++k) { + // Check offset + wf_offset_t offset = offsets[k]; + if (offset == WAVEFRONT_OFFSET_NULL) continue; + // Count equal characters + int v = WAVEFRONT_V(k,offset); + int h = WAVEFRONT_H(k,offset); + while (wavefront_sequences_cmp(seqs,v,h)) { + h++; v++; offset++; + } + // Update offset + offsets[k] = offset; + // Compute max + const wf_offset_t antidiag = WAVEFRONT_ANTIDIAGONAL(k,offset); + if (*max_antidiag < antidiag) *max_antidiag = antidiag; + // Check ends-free reaching boundaries + if (endsfree && wavefront_termination_endsfree(wf_aligner,mwavefront,score,k,offset)) { + return true; // Quit (we are done) + } + } + // Alignment not finished + return false; +} diff --git a/src/common/wflign/deps/WFA2-lib/utils/string_padded.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h similarity index 57% rename from src/common/wflign/deps/WFA2-lib/utils/string_padded.h rename to src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h index 975594d8..d0a28eb0 100644 --- a/src/common/wflign/deps/WFA2-lib/utils/string_padded.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels.h @@ -26,48 +26,44 @@ * * PROJECT: Wavefront Alignment Algorithms * AUTHOR(S): Santiago Marco-Sola - * DESCRIPTION: Padded string module to avoid handling corner conditions + * DESCRIPTION: WFA module for the "extension" of exact matches */ -#ifndef STRING_PADDED_H_ -#define STRING_PADDED_H_ +#ifndef WAVEFRONT_EXTEND_KERNELS_H_ +#define WAVEFRONT_EXTEND_KERNELS_H_ + +#include "wavefront_aligner.h" /* - * Strings Padded + * Wavefront-Extend Inner Kernels */ -typedef struct { - // Dimensions - int pattern_length; - int text_length; - // Padded strings - char* pattern_padded; - char* text_padded; - // MM - char* pattern_padded_buffer; - char* text_padded_buffer; - mm_allocator_t* mm_allocator; -} strings_padded_t; +void wavefront_extend_matches_packed_end2end( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi); +wf_offset_t wavefront_extend_matches_packed_end2end_max( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi); +bool wavefront_extend_matches_packed_endsfree( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi); /* - * Strings (text/pattern) padded + * Wavefront-Extend Inner Kernel (Custom match function) */ -strings_padded_t* strings_padded_new( - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const int padding_length, - const bool reverse_sequences, - mm_allocator_t* const mm_allocator); -strings_padded_t* strings_padded_new_rhomb( - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const int padding_length, - const bool reverse_sequences, - mm_allocator_t* const mm_allocator); -void strings_padded_delete( - strings_padded_t* const strings_padded); +bool wavefront_extend_matches_custom( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int lo, + const int hi, + const bool endsfree, + wf_offset_t* const max_antidiag); -#endif /* STRING_PADDED_H_ */ +#endif /* WAVEFRONT_EXTEND_KERNELS_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c new file mode 100644 index 00000000..b31d8d55 --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.c @@ -0,0 +1,167 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches + */ + +#include "wavefront_extend.h" +#include "wavefront_align.h" +#include "wavefront_compute.h" +#include "wavefront_heuristic.h" +#include "wavefront_extend_kernels.h" +#include "wavefront_extend_kernels_avx.h" + +#if __AVX2__ +#include +/* + * Wavefront-Extend Inner Kernel (Scalar) + */ +FORCE_INLINE wf_offset_t wavefront_extend_matches_packed_kernel( + wavefront_aligner_t* const wf_aligner, + const int k, + wf_offset_t offset) { + // Fetch pattern/text blocks + uint64_t* pattern_blocks = (uint64_t*)(wf_aligner->sequences.pattern+WAVEFRONT_V(k,offset)); + uint64_t* text_blocks = (uint64_t*)(wf_aligner->sequences.text+WAVEFRONT_H(k,offset)); + // Compare 64-bits blocks + uint64_t cmp = *pattern_blocks ^ *text_blocks; + while (__builtin_expect(cmp==0,0)) { + // Increment offset (full block) + offset += 8; + // Next blocks + ++pattern_blocks; + ++text_blocks; + // Compare + cmp = *pattern_blocks ^ *text_blocks; + } + // Count equal characters + const int equal_right_bits = __builtin_ctzl(cmp); + const int equal_chars = DIV_FLOOR(equal_right_bits,8); + offset += equal_chars; + // Return extended offset + return offset; +} +/* + * SIMD clz, use a native instruction when available (AVX512 CD or VL + * extensions), or emulate the clz behavior. + */ +FORCE_INLINE __m256i avx2_lzcnt_epi32(__m256i v) { +#if __AVX512CD__ && __AVX512VL__ + return _mm256_lzcnt_epi32(v); +#else + // Emulate clz for AVX2: https://stackoverflow.com/a/58827596 + v = _mm256_andnot_si256(_mm256_srli_epi32(v,8),v); // keep 8 MSB + v = _mm256_castps_si256(_mm256_cvtepi32_ps(v)); // convert an integer to float + v = _mm256_srli_epi32(v,23); // shift down the exponent + v = _mm256_subs_epu16(_mm256_set1_epi32(158),v); // undo bias + v = _mm256_min_epi16(v,_mm256_set1_epi32(32)); // clamp at 32 + return v; +#endif +} +/* + * Wavefront-Extend Inner Kernel (SIMD AVX2/AVX512) + */ +FORCE_NO_INLINE void wavefront_extend_matches_packed_end2end_avx2( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi) { + // Parameters + wf_offset_t* const offsets = mwavefront->offsets; + int k_min = lo; + int k_max = hi; + const char* pattern = wf_aligner->sequences.pattern; + const char* text = wf_aligner->sequences.text; + const __m256i vector_null = _mm256_set1_epi32(-1); + const __m256i fours = _mm256_set1_epi32(4); + const __m256i eights = _mm256_set1_epi32(8); + const __m256i vecShuffle = _mm256_set_epi8(28,29,30,31,24,25,26,27, + 20,21,22,23,16,17,18,19, + 12,13,14,15, 8, 9,10,11, + 4 , 5, 6, 7, 0, 1, 2 ,3); + const int elems_per_register = 8; + int num_of_diagonals = k_max - k_min + 1; + int loop_peeling_iters = num_of_diagonals % elems_per_register; + int k; + for (k=k_min;k= 0) { + offsets[curr_k] = wavefront_extend_matches_packed_kernel(wf_aligner,curr_k,offset); + } else { + offsets[curr_k] = WAVEFRONT_OFFSET_NULL; + } + mask &= (0xfffffff0 << tz); + } + } +} + +#endif // AVX2 diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h new file mode 100644 index 00000000..0e932d4e --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_extend_kernels_avx.h @@ -0,0 +1,47 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WaveFront-Alignment module for the "extension" of exact matches + */ + +#ifndef WAVEFRONT_EXTEND_AVX_H_ +#define WAVEFRONT_EXTEND_AVX_H_ + +#if __AVX2__ + +#include "wavefront_aligner.h" + +void wavefront_extend_matches_packed_end2end_avx2( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int lo, + const int hi); + +#endif // AVX2 + +#endif /* WAVEFRONT_EXTEND_AVX_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c index 73ada3e3..c8845608 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.c @@ -259,8 +259,9 @@ void wavefront_heuristic_wfadaptive( wavefront_t* const wavefront, const bool wfmash_mode) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; const int min_wavefront_length = wf_aligner->heuristic.min_wavefront_length; const int max_distance_threshold = wf_aligner->heuristic.max_distance_threshold; wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; @@ -303,7 +304,7 @@ void wf_heuristic_compute_sw_scores( wf_offset_t* const max_offset) { // Parameters const int wf_match = wf_aligner->penalties.match; - const int swg_match = (wf_match==0) ? 1 : -(wf_aligner->penalties.match); + const int swg_match = (wf_match!=0) ? -(wf_aligner->penalties.match) : -1; // Compute min-distance const wf_offset_t* const offsets = wavefront->offsets; int k, cmax_sw_score = INT_MIN, cmax_k = 0, cmax_offset = 0; @@ -313,9 +314,7 @@ void wf_heuristic_compute_sw_scores( if (offset < 0) continue; const int v = WAVEFRONT_V(k,offset); const int h = WAVEFRONT_H(k,offset); - const int sw_score = (wf_match==0) ? - (swg_match*(v+h) - wf_score) : - WF_SCORE_TO_SW_SCORE(swg_match,v,h,wf_score); + const int sw_score = WF_SCORE_TO_SW_SCORE(swg_match,v,h,wf_score); sw_scores[k] = sw_score; if (cmax_sw_score < sw_score) { cmax_sw_score = sw_score; @@ -383,19 +382,22 @@ void wavefront_heuristic_xdrop( wf_heuristic->steps_wait = wf_heuristic->steps_between_cutoffs; } int wf_zdrop_gap_score( - const int gap_extension_penalty, + wavefront_aligner_t* const wf_aligner, const wf_offset_t offset_1, const int k_1, const wf_offset_t offset_2, const int k_2) { + // Parameters + const int gap_e = wf_aligner->penalties.internal_gap_e; + // Compute int diff_h = WAVEFRONT_H(k_2,offset_2) - WAVEFRONT_H(k_1,offset_1); if (diff_h < 0) diff_h = -diff_h; int diff_v = WAVEFRONT_V(k_2,offset_2) - WAVEFRONT_V(k_1,offset_1); if (diff_v < 0) diff_v = -diff_v; const int gap_length = (diff_h >= diff_v) ? diff_h-diff_v : diff_v-diff_h; - return gap_length * gap_extension_penalty; + return gap_length * gap_e; } -void wavefront_heuristic_zdrop( +bool wavefront_heuristic_zdrop( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront, const int score) { @@ -404,7 +406,7 @@ void wavefront_heuristic_zdrop( const int base_hi = wavefront->hi; const int base_lo = wavefront->lo; // Check steps - if (wf_heuristic->steps_wait > 0) return; + if (wf_heuristic->steps_wait > 0) return false; // Use victim as temporal buffer wavefront_components_resize_null__victim(&wf_aligner->wf_components,base_lo-1,base_hi+1); wf_offset_t* const sw_scores = wf_aligner->wf_components.wavefront_victim->offsets; @@ -414,8 +416,6 @@ void wavefront_heuristic_zdrop( wf_aligner,wavefront,score,sw_scores, &cmax_sw_score,&cmax_k,&cmax_offset); // Apply Z-Drop - wavefront_penalties_t* const penalties = &wf_aligner->penalties; - const int gap_e = (penalties->gap_extension1 > 0) ? penalties->gap_extension1 : 1; const int zdrop = wf_heuristic->zdrop; const int max_sw_score = wf_heuristic->max_sw_score; const int max_k = wf_heuristic->max_sw_score_k; @@ -424,29 +424,29 @@ void wavefront_heuristic_zdrop( // Update maximum score observed if (cmax_sw_score > wf_heuristic->max_sw_score) { wf_heuristic->max_sw_score = cmax_sw_score; + wf_heuristic->max_wf_score = score; wf_heuristic->max_sw_score_k = cmax_k; wf_heuristic->max_sw_score_offset = cmax_offset; } else { // Test Z-drop - const int gap_score = wf_zdrop_gap_score(gap_e,max_offset,max_k,cmax_offset,cmax_k); - // fprintf(stderr,"[Z-DROP] (max=%d~(%d,%d),current=%d~(%d,%d)) diff=%d leeway=%d\n", - // max_sw_score,WAVEFRONT_V(max_k,max_offset),WAVEFRONT_H(max_k,max_offset), - // cmax_sw_score,WAVEFRONT_V(cmax_k,cmax_offset),WAVEFRONT_H(cmax_k,cmax_offset), - // max_sw_score - cmax_sw_score, - // zdrop + gap_score); - if (max_sw_score - (int)cmax_sw_score > zdrop + gap_score) { - wavefront->lo = wavefront->hi + 1; - return; // Z-dropped + if (max_sw_score - (int)cmax_sw_score > zdrop) { + wf_aligner->alignment_end_pos.score = wf_heuristic->max_wf_score; + wf_aligner->alignment_end_pos.k = max_k; + wf_aligner->alignment_end_pos.offset = max_offset; + return true; // Z-dropped } } } else { // Update maximum score observed wf_heuristic->max_sw_score = cmax_sw_score; + wf_heuristic->max_wf_score = score; wf_heuristic->max_sw_score_k = cmax_k; wf_heuristic->max_sw_score_offset = cmax_offset; } // Set wait steps (don't repeat this heuristic often) wf_heuristic->steps_wait = wf_heuristic->steps_between_cutoffs; + // Return NOT Z-dropped + return false; } /* * Heuristic Cut-off Banded @@ -464,8 +464,9 @@ void wavefront_heuristic_banded_adaptive( wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; // Check steps if (wf_heuristic->steps_wait > 0) return; @@ -505,7 +506,7 @@ void wavefront_heuristic_banded_adaptive( /* * Heuristic Cut-offs dispatcher */ -void wavefront_heuristic_cufoff( +bool wavefront_heuristic_cufoff( wavefront_aligner_t* const wf_aligner, const int score, const int score_mod) { @@ -515,7 +516,7 @@ void wavefront_heuristic_cufoff( wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; // Fetch m-wavefront wavefront_t* const mwavefront = wf_components->mwavefronts[score_mod]; - if (mwavefront == NULL || mwavefront->lo > mwavefront->hi) return; + if (mwavefront == NULL || mwavefront->lo > mwavefront->hi) return false; // Not Dropped // Decrease wait steps --(wf_heuristic->steps_wait); // Save lo/hi base @@ -531,7 +532,7 @@ void wavefront_heuristic_cufoff( if (wf_heuristic->strategy & wf_heuristic_xdrop) { wavefront_heuristic_xdrop(wf_aligner,mwavefront,score); } else if (wf_heuristic->strategy & wf_heuristic_zdrop) { - wavefront_heuristic_zdrop(wf_aligner,mwavefront,score); + if (wavefront_heuristic_zdrop(wf_aligner,mwavefront,score)) return true; // Z-Dropped } // Select heuristic (Banded) if (wf_heuristic->strategy & wf_heuristic_banded_static) { @@ -540,7 +541,7 @@ void wavefront_heuristic_cufoff( wavefront_heuristic_banded_adaptive(wf_aligner,mwavefront); } // Check wavefront length - if (lo_base == mwavefront->lo && hi_base == mwavefront->hi) return; // No wavefronts pruned + if (lo_base == mwavefront->lo && hi_base == mwavefront->hi) return false; // No wavefronts pruned if (mwavefront->lo > mwavefront->hi) mwavefront->null = true; // DEBUG // const int wf_length_base = hi_base-lo_base+1; @@ -551,17 +552,18 @@ void wavefront_heuristic_cufoff( mwavefront->wf_elements_init_min = mwavefront->lo; mwavefront->wf_elements_init_max = mwavefront->hi; // Equate other wavefronts - if (distance_metric <= gap_linear) return; + if (distance_metric <= gap_linear) return false; // Not Dropped // Cut-off the other wavefronts (same dimensions as M) wavefront_t* const i1wavefront = wf_components->i1wavefronts[score_mod]; wavefront_t* const d1wavefront = wf_components->d1wavefronts[score_mod]; wf_heuristic_equate(i1wavefront,mwavefront); wf_heuristic_equate(d1wavefront,mwavefront); - if (distance_metric == gap_affine) return; + if (distance_metric == gap_affine) return false; // Not Dropped wavefront_t* const i2wavefront = wf_components->i2wavefronts[score_mod]; wavefront_t* const d2wavefront = wf_components->d2wavefronts[score_mod]; wf_heuristic_equate(i2wavefront,mwavefront); wf_heuristic_equate(d2wavefront,mwavefront); + return false; // Not Dropped } /* * Display diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.h index f59634ef..b230a419 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_heuristic.h @@ -62,7 +62,8 @@ typedef struct { int zdrop; // Z-drop parameter // Internals int steps_wait; // Score-steps until next cut-off - int max_sw_score; // Maximum score observed (for x/z drops) + int max_sw_score; // Maximum swg-score observed (for x/z drops) + int max_wf_score; // Corresponding wf-score (to max_sw_score) int max_sw_score_offset; // Offset of the maximum score observed int max_sw_score_k; // Diagonal of the maximum score observed } wavefront_heuristic_t; @@ -109,7 +110,7 @@ void wavefront_heuristic_clear( /* * Wavefront heuristic cut-off */ -void wavefront_heuristic_cufoff( +bool wavefront_heuristic_cufoff( wavefront_aligner_t* const wf_aligner, const int score, const int score_mod); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c index 1d90db98..4f6964ca 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.c @@ -152,17 +152,16 @@ int pcigar_unpack_extend_custom( */ void pcigar_unpack_linear( pcigar_t pcigar, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, int* const v_pos, int* const h_pos, char* cigar_buffer, int* const cigar_length) { // Parameters + char* const pattern = sequences->pattern; + const int pattern_length = sequences->pattern_length; + char* const text = sequences->text; + const int text_length = sequences->text_length; char* const cigar_buffer_base = cigar_buffer; // Compute pcigar length and shift to the end of the word int pcigar_length = PCIGAR_MAX_LENGTH; @@ -176,10 +175,10 @@ void pcigar_unpack_linear( for (i=0;imode == wf_sequences_lambda) { // Custom extend-match function num_matches = pcigar_unpack_extend_custom( - pattern_length,text_length, - match_funct,match_funct_arguments,v,h,cigar_buffer); + pattern_length,text_length,sequences->match_funct, + sequences->match_funct_arguments,v,h,cigar_buffer); } else { num_matches = pcigar_unpack_extend( pattern,pattern_length,text,text_length,v,h,cigar_buffer); @@ -204,18 +203,17 @@ void pcigar_unpack_linear( } void pcigar_unpack_affine( pcigar_t pcigar, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, int* const v_pos, int* const h_pos, char* cigar_buffer, int* const cigar_length, affine_matrix_type* const current_matrix_type) { // Parameters + char* const pattern = sequences->pattern; + const int pattern_length = sequences->pattern_length; + char* const text = sequences->text; + const int text_length = sequences->text_length; char* const cigar_buffer_base = cigar_buffer; // Compute pcigar length and shift to the end of the word int pcigar_length = PCIGAR_MAX_LENGTH; @@ -231,10 +229,10 @@ void pcigar_unpack_affine( // Extend exact-matches if (matrix_type == affine_matrix_M) { // Extend only on the M-wavefront int num_matches; - if (match_funct != NULL) { // Custom extend-match function + if (sequences->mode == wf_sequences_lambda) { // Custom extend-match function num_matches = pcigar_unpack_extend_custom( - pattern_length,text_length, - match_funct,match_funct_arguments,v,h,cigar_buffer); + pattern_length,text_length,sequences->match_funct, + sequences->match_funct_arguments,v,h,cigar_buffer); } else { num_matches = pcigar_unpack_extend( pattern,pattern_length,text,text_length,v,h,cigar_buffer); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h index 803fcc26..0f2edb7e 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_pcigar.h @@ -33,6 +33,7 @@ #define WAVEFRONT_PACKED_CIGAR_H_ #include "wavefront_attributes.h" +#include "wavefront_sequences.h" /* * Configuration @@ -90,24 +91,14 @@ int pcigar_unpack( */ void pcigar_unpack_linear( pcigar_t pcigar, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, int* const v_pos, int* const h_pos, char* cigar_buffer, int* const cigar_length); void pcigar_unpack_affine( pcigar_t pcigar, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - alignment_match_funct_t const match_funct, - void* const match_funct_arguments, + wavefront_sequences_t* const sequences, int* const v_pos, int* const h_pos, char* cigar_buffer, diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.c index 45b933e1..c6e85823 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.c @@ -88,6 +88,9 @@ void wavefront_penalties_set_linear( wf_penalties->gap_extension1 = -1; wf_penalties->gap_opening2 = -1; wf_penalties->gap_extension2 = -1; + // Internals + wf_penalties->linear_penalties = *linear_penalties; + wf_penalties->internal_gap_e = linear_penalties->indel; } void wavefront_penalties_set_affine( wavefront_penalties_t* const wf_penalties, @@ -122,6 +125,9 @@ void wavefront_penalties_set_affine( // Set unused wf_penalties->gap_opening2 = -1; wf_penalties->gap_extension2 = -1; + // Internals + wf_penalties->affine_penalties = *affine_penalties; + wf_penalties->internal_gap_e = affine_penalties->gap_extension; } void wavefront_penalties_set_affine2p( wavefront_penalties_t* const wf_penalties, @@ -133,9 +139,9 @@ void wavefront_penalties_set_affine2p( fprintf(stderr,"[WFA::Penalties] Match score must be negative or zero (M=%d)\n",affine2p_penalties->match); exit(1); } else if (affine2p_penalties->mismatch <= 0 || - affine2p_penalties->gap_opening1 <= 0 || + affine2p_penalties->gap_opening1 < 0 || affine2p_penalties->gap_extension1 <= 0 || - affine2p_penalties->gap_opening2 <= 0 || + affine2p_penalties->gap_opening2 < 0 || affine2p_penalties->gap_extension2 <= 0) { fprintf(stderr,"[WFA::Penalties] Penalties (X=%d,O1=%d,E1=%d,O2=%d,E2=%d) must be (X>0,O1>=0,E1>0,O1>=0,E1>0)\n", affine2p_penalties->mismatch, @@ -161,6 +167,9 @@ void wavefront_penalties_set_affine2p( wf_penalties->gap_opening2 = affine2p_penalties->gap_opening2; wf_penalties->gap_extension2 = affine2p_penalties->gap_extension2; } + // Internals + wf_penalties->affine2p_penalties = *affine2p_penalties; + wf_penalties->internal_gap_e = affine2p_penalties->gap_extension1; } /* * Display @@ -171,29 +180,32 @@ void wavefront_penalties_print( // Select penalties mode switch (wf_penalties->distance_metric) { case indel: - fprintf(stream,"(Indel)"); + fprintf(stream,"(Indel,0,inf,1)"); break; case edit: - fprintf(stream,"(Edit)"); + fprintf(stream,"(Edit,0,1,1)"); break; case gap_linear: - fprintf(stream,"(GapLinear,%d,%d)", - wf_penalties->mismatch, - wf_penalties->gap_opening1); + fprintf(stream,"(GapLinear,%d,%d,%d)", + wf_penalties->linear_penalties.match, + wf_penalties->linear_penalties.mismatch, + wf_penalties->linear_penalties.indel); break; case gap_affine: - fprintf(stream,"(GapAffine,%d,%d,%d)", - wf_penalties->mismatch, - wf_penalties->gap_opening1, - wf_penalties->gap_extension1); + fprintf(stream,"(GapAffine,%d,%d,%d,%d)", + wf_penalties->affine_penalties.match, + wf_penalties->affine_penalties.mismatch, + wf_penalties->affine_penalties.gap_opening, + wf_penalties->affine_penalties.gap_extension); break; case gap_affine_2p: - fprintf(stream,"(GapAffine2p,%d,%d,%d,%d,%d)", - wf_penalties->mismatch, - wf_penalties->gap_opening1, - wf_penalties->gap_extension1, - wf_penalties->gap_opening2, - wf_penalties->gap_extension2); + fprintf(stream,"(GapAffine2p,%d,%d,%d,%d,%d,%d)", + wf_penalties->affine2p_penalties.match, + wf_penalties->affine2p_penalties.mismatch, + wf_penalties->affine2p_penalties.gap_opening1, + wf_penalties->affine2p_penalties.gap_extension1, + wf_penalties->affine2p_penalties.gap_opening2, + wf_penalties->affine2p_penalties.gap_extension2); break; default: break; diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.h index 97c752c0..09330760 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_penalties.h @@ -51,13 +51,20 @@ typedef enum { * Wavefront Penalties */ typedef struct { - distance_metric_t distance_metric; // Alignment metric/distance used - int match; // (M <= 0) (Internal variable change to M=0 for WFA) + // Alignment metric/distance used + distance_metric_t distance_metric; + // Penalty values + int match; // (M <= 0) int mismatch; // (X > 0) int gap_opening1; // (O1 >= 0) int gap_extension1; // (E1 > 0) int gap_opening2; // (O2 >= 0) int gap_extension2; // (E2 > 0) + // Internals + linear_penalties_t linear_penalties; // Original gap-linear penalties + affine_penalties_t affine_penalties; // Original gap-affine penalties + affine2p_penalties_t affine2p_penalties; // Original gap-affine2p penalties + int internal_gap_e; // Original gap-extension value (used for z-drop) } wavefront_penalties_t; /* diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c index a7ca0412..9905cd26 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.c @@ -99,9 +99,6 @@ wavefront_plot_t* wavefront_plot_new( wf_plot->max_h = -1; // Allocate and configure wavefront_plot_heatmaps_allocate(wf_plot,pattern_length,text_length); - // Clear offsets - wf_plot->offset_h = 0; - wf_plot->offset_v = 0; // Return return wf_plot; } @@ -113,9 +110,6 @@ void wavefront_plot_resize( wavefront_plot_heatmaps_free(wf_plot); // Allocate new heatmaps wavefront_plot_heatmaps_allocate(wf_plot,pattern_length,text_length); - // Clear offsets - wf_plot->offset_h = 0; - wf_plot->offset_v = 0; } void wavefront_plot_delete( wavefront_plot_t* const wf_plot) { @@ -136,11 +130,13 @@ void wavefront_plot_component( // Check wavefront if (wavefront == NULL) return; // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; - const char* const pattern = wf_aligner->pattern; - const char* const text = wf_aligner->text; - wavefront_plot_t* const plot = wf_aligner->plot; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_begin = sequences->pattern_begin; + const int pattern_length = sequences->pattern_length; + const int text_begin = sequences->text_begin; + const int text_length = sequences->text_length; + const char* const pattern = sequences->pattern; + const char* const text = sequences->text; const bool reverse = (wf_aligner->align_mode == wf_align_biwfa_breakpoint_reverse); // Traverse all offsets int k; @@ -155,11 +151,11 @@ void wavefront_plot_component( // Compute global coordinates int v_global, h_global; if (reverse) { - v_global = plot->offset_v + (pattern_length - 1 - v_local); - h_global = plot->offset_h + (text_length - 1 - h_local); + v_global = pattern_begin + (pattern_length - 1 - v_local); + h_global = text_begin + (text_length - 1 - h_local); } else { - v_global = plot->offset_v + v_local; - h_global = plot->offset_h + h_local; + v_global = pattern_begin + v_local; + h_global = text_begin + h_local; } // Plot if (reverse) { @@ -191,7 +187,6 @@ void wavefront_plot( wavefront_aligner_t* const wf_aligner, const int score, const int align_level) { - //if (wf_aligner->align_mode == wf_align_biwfa_breakpoint_forward) return; // Check plotting enabled wrt align-level if (wf_aligner->align_mode == wf_align_biwfa_breakpoint_forward || wf_aligner->align_mode == wf_align_biwfa_breakpoint_reverse) { @@ -254,28 +249,41 @@ void wavefront_plot_print( // Parameters const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; wavefront_plot_t* const wf_plot = wf_aligner->plot; + wavefront_sequences_t* sequences = NULL; + if (wf_aligner->bialigner == NULL) { + sequences = &wf_aligner->sequences; + } else { + sequences = &wf_aligner->bialigner->wf_forward->sequences; + wavefront_sequences_set_bounds(sequences, + 0,sequences->pattern_buffer_length, + 0,sequences->text_buffer_length); + } + const int pattern_length = sequences->pattern_buffer_length; + const int text_length = sequences->text_buffer_length; + // Check plot + if (wf_aligner->plot == NULL) { + fprintf(stream,"# WFA-plot not enabled\n"); + return; + } // Metadata - if (wf_aligner->match_funct != NULL) { - fprintf(stream,"# PatternLength 0\n"); - fprintf(stream,"# TextLength 0\n"); + if (sequences->mode == wf_sequences_lambda) { + fprintf(stream,"# PatternLength %d\n",pattern_length); + fprintf(stream,"# TextLength %d\n",text_length); fprintf(stream,"# Pattern -\n"); fprintf(stream,"# Text -\n"); } else { - fprintf(stream,"# PatternLength %d\n",wf_aligner->pattern_length); - fprintf(stream,"# Pattern %.*s\n",wf_aligner->pattern_length,wf_aligner->pattern); - fprintf(stream,"# TextLength %d\n",wf_aligner->text_length); - fprintf(stream,"# Text %.*s\n",wf_aligner->text_length,wf_aligner->text); + fprintf(stream,"# PatternLength %d\n",pattern_length); + fprintf(stream,"# Pattern %.*s\n",pattern_length,sequences->pattern); + fprintf(stream,"# TextLength %d\n",text_length); + fprintf(stream,"# Text %.*s\n",text_length,sequences->text); } fprintf(stream,"# Penalties "); wavefront_penalties_print(stream,&wf_aligner->penalties); fprintf(stream,"\n"); // Alignment mode fprintf(stream,"# WFAMode "); - wavefront_aligner_print_mode(stream,wf_aligner); wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic; - if (wf_heuristic->strategy != wf_heuristic_none) { - wavefront_heuristic_print(stream,wf_heuristic); - } + wavefront_heuristic_print(stream,wf_heuristic); fprintf(stream,"\n"); // Wavefront components fprintf(stream,"# Heatmap M\n"); heatmap_print(stream,wf_plot->m_heatmap); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.h index fb0cf11a..62a32584 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_plot.h @@ -62,9 +62,6 @@ typedef struct { heatmap_t* i2_heatmap; heatmap_t* d2_heatmap; heatmap_t* behavior_heatmap; - // Offsets - int offset_h; - int offset_v; } wavefront_plot_t; /* diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c new file mode 100644 index 00000000..4551537d --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.c @@ -0,0 +1,310 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WFA module to encapsulate the input sequences + */ + +#include "wavefront_sequences.h" + +/* + * Configuration + */ +#define WF_SEQUENCES_PADDING 64 +#define WF_SEQUENCES_PATTERN_EOS '!' +#define WF_SEQUENCES_TEXT_EOS '?' + +/* + * Setup + */ +void wavefront_sequences_allocate( + wavefront_sequences_t* const wf_sequences) { + // Mode + wf_sequences->mode = wf_sequences_ascii; + wf_sequences->reverse = false; + // Source sequences + wf_sequences->seq_buffer = NULL; + wf_sequences->seq_buffer_allocated = 0; + // Current state + wf_sequences->pattern = NULL; + wf_sequences->text = NULL; +} +void wavefront_sequences_free( + wavefront_sequences_t* const wf_sequences) { + // Free internal buffers + if (wf_sequences->seq_buffer != NULL) free(wf_sequences->seq_buffer); +} +/* + * Init Sequences + */ +void wavefront_sequences_init_allocate( + wavefront_sequences_t* const wf_sequences, + const int pattern_length, + const int text_length) { + // Compute dimensions + const int buffer_size = pattern_length + text_length + 3*WF_SEQUENCES_PADDING; + // Check internal buffer allocated + if (wf_sequences->seq_buffer_allocated < buffer_size) { + // Free + if (wf_sequences->seq_buffer != NULL) free(wf_sequences->seq_buffer); + // Allocate + const int proposed_size = buffer_size + buffer_size/2; + wf_sequences->seq_buffer = malloc(proposed_size); + wf_sequences->seq_buffer_allocated = proposed_size; + } + // Assign memory + wf_sequences->pattern_buffer = wf_sequences->seq_buffer + WF_SEQUENCES_PADDING; + wf_sequences->text_buffer = wf_sequences->seq_buffer + WF_SEQUENCES_PADDING + pattern_length + WF_SEQUENCES_PADDING; +} +void wavefront_sequences_init_copy( + char* const buffer_dst, + const char* const sequence, + const int sequence_length, + const int padding_length, + const char padding_value, + const bool reverse) { + // Copy sequence + if (reverse) { + int i; + for (i=0;i>2 & 3)]; + const char letter2 = dna_packed2bits_decode[(word>>4 & 3)]; + const char letter3 = dna_packed2bits_decode[(word>>6 & 3)]; + if (reverse) { + buffer_dst[buffer_pos ] = letter0; + buffer_dst[buffer_pos-1] = letter1; + buffer_dst[buffer_pos-2] = letter2; + buffer_dst[buffer_pos-3] = letter3; + buffer_pos -= 4; + } else { + buffer_dst[buffer_pos ] = letter0; + buffer_dst[buffer_pos+1] = letter1; + buffer_dst[buffer_pos+2] = letter2; + buffer_dst[buffer_pos+3] = letter3; + buffer_pos += 4; + } + } + // Add end padding + buffer_dst[sequence_length] = padding_value; +} +void wavefront_sequences_init_ascii( + wavefront_sequences_t* const wf_sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const bool reverse) { + // Mode + wf_sequences->mode = wf_sequences_ascii; + wf_sequences->reverse = reverse; + // Allocate buffers + wavefront_sequences_init_allocate(wf_sequences,pattern_length,text_length); + // Copy internal sequences + wavefront_sequences_init_copy(wf_sequences->pattern_buffer, + pattern,pattern_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_PATTERN_EOS,reverse); + wf_sequences->pattern_buffer_length = pattern_length; + wavefront_sequences_init_copy(wf_sequences->text_buffer, + text,text_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_TEXT_EOS,reverse); + wf_sequences->text_buffer_length = text_length; + // Set pattern + wf_sequences->pattern = wf_sequences->pattern_buffer; + wf_sequences->pattern_begin = 0; + wf_sequences->pattern_length = pattern_length; + wf_sequences->pattern_eos = wf_sequences->pattern[pattern_length]; + // Set text + wf_sequences->text = wf_sequences->text_buffer; + wf_sequences->text_begin = 0; + wf_sequences->text_length = text_length; + wf_sequences->text_eos = wf_sequences->text[text_length]; +} +void wavefront_sequences_init_lambda( + wavefront_sequences_t* const wf_sequences, + alignment_match_funct_t match_funct, + void* match_funct_arguments, + const int pattern_length, + const int text_length, + const bool reverse) { + // Mode + wf_sequences->mode = wf_sequences_lambda; + wf_sequences->reverse = reverse; + // Set sequences' length + wf_sequences->pattern = NULL; + wf_sequences->text = NULL; + wf_sequences->pattern_begin = 0; + wf_sequences->pattern_length = pattern_length; + wf_sequences->text_begin = 0; + wf_sequences->text_length = text_length; + // Internals + wf_sequences->match_funct = match_funct; + wf_sequences->match_funct_arguments = match_funct_arguments; +} +void wavefront_sequences_init_packed2bits( + wavefront_sequences_t* const wf_sequences, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length, + const bool reverse) { + // Mode + wf_sequences->mode = wf_sequences_ascii; + wf_sequences->reverse = reverse; + // Allocate buffers + wavefront_sequences_init_allocate(wf_sequences,pattern_length,text_length); + // Copy internal sequences + wavefront_sequences_init_decode2bits(wf_sequences->pattern_buffer, + pattern,pattern_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_PATTERN_EOS,reverse); + wf_sequences->pattern_buffer_length = pattern_length; + wavefront_sequences_init_decode2bits(wf_sequences->text_buffer, + text,text_length,WF_SEQUENCES_PADDING,WF_SEQUENCES_TEXT_EOS,reverse); + wf_sequences->text_buffer_length = text_length; + // Set pattern + wf_sequences->pattern = wf_sequences->pattern_buffer; + wf_sequences->pattern_begin = 0; + wf_sequences->pattern_length = pattern_length; + wf_sequences->pattern_eos = wf_sequences->pattern[pattern_length]; + // Set text + wf_sequences->text = wf_sequences->text_buffer; + wf_sequences->text_begin = 0; + wf_sequences->text_length = text_length; + wf_sequences->text_eos = wf_sequences->text[text_length]; +} +/* + * Accessors + */ +bool wavefront_sequences_cmp( + wavefront_sequences_t* const wf_sequences, + const int pattern_pos, + const int text_pos) { + // Select mode + if (wf_sequences->mode == wf_sequences_lambda) { + // Custom function to compare sequences + alignment_match_funct_t match_funct = wf_sequences->match_funct; + void* match_funct_arguments = wf_sequences->match_funct_arguments; + // Check coordinates (EOS) + const int pattern_length = wf_sequences->pattern_length; + const int text_length = wf_sequences->text_length; + if (pattern_pos >= pattern_length || text_pos >= text_length) return false; + // Compare using lambda (given coordinates) + const int pattern_begin = wf_sequences->pattern_begin; + const int text_begin = wf_sequences->text_begin; + if (wf_sequences->reverse) { + const int pattern_end = pattern_begin + pattern_length - 1; + const int text_end = text_begin + text_length - 1; + return match_funct(pattern_end-pattern_pos,text_end-text_pos,match_funct_arguments); + } else { + return match_funct(pattern_begin+pattern_pos,text_begin+text_pos,match_funct_arguments); + } + } else { + // Compare regular strings + return wf_sequences->pattern[pattern_pos] == wf_sequences->text[text_pos]; + } +} +char wavefront_sequences_get_pattern( + wavefront_sequences_t* const wf_sequences, + const int position) { + if (wf_sequences->mode == wf_sequences_lambda) { + return '-'; + } else { + return wf_sequences->pattern[position]; + } +} +char wavefront_sequences_get_text( + wavefront_sequences_t* const wf_sequences, + const int position) { + if (wf_sequences->mode == wf_sequences_lambda) { + return '-'; + } else { + return wf_sequences->text[position]; + } +} +/* + * Resize/Update + */ +void wavefront_sequences_set_bounds( + wavefront_sequences_t* const wf_sequences, + const int pattern_begin, + const int pattern_end, + const int text_begin, + const int text_end) { + // Select mode + if (wf_sequences->mode != wf_sequences_lambda) { + // Restore previous EOS char + const int pattern_length_old = wf_sequences->pattern_length; + const int text_length_old = wf_sequences->text_length; + wf_sequences->pattern[pattern_length_old] = wf_sequences->pattern_eos; + wf_sequences->text[text_length_old] = wf_sequences->text_eos; + // Focus on the new section of the sequences + if (wf_sequences->reverse) { + // Compare given coordinates + wf_sequences->pattern = wf_sequences->pattern_buffer + (wf_sequences->pattern_buffer_length - pattern_end); + wf_sequences->text = wf_sequences->text_buffer + (wf_sequences->text_buffer_length - text_end); + } else { + wf_sequences->pattern = wf_sequences->pattern_buffer + pattern_begin; + wf_sequences->text = wf_sequences->text_buffer + text_begin; + } + // Save EOS char and truncate sequence + const int pattern_length_new = pattern_end - pattern_begin; + const int text_length_new = text_end - text_begin; + wf_sequences->pattern_eos = wf_sequences->pattern[pattern_length_new]; + wf_sequences->text_eos = wf_sequences->text[text_length_new]; + wf_sequences->pattern[pattern_length_new] = WF_SEQUENCES_PATTERN_EOS; + wf_sequences->text[text_length_new] = WF_SEQUENCES_TEXT_EOS; + } + // Set bounds + wf_sequences->pattern_begin = pattern_begin; + wf_sequences->pattern_length = pattern_end - pattern_begin; + wf_sequences->text_begin = text_begin; + wf_sequences->text_length = text_end - text_begin; +} + diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h new file mode 100644 index 00000000..7e047c3c --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_sequences.h @@ -0,0 +1,148 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WFA module to encapsulate the input sequences + */ + +#ifndef WAVEFRONT_SEQUENCES_H_ +#define WAVEFRONT_SEQUENCES_H_ + +#include "utils/commons.h" + +/* + * Custom extend-match function, e.g.: + * + * typedef struct { + * char* pattern; + * int pattern_length; + * char* text; + * int text_length; + * } match_function_params_t; + * + * int match_function(int v,int h,void* arguments) { + * // Extract parameters + * match_function_params_t* match_arguments = (match_function_params_t*)arguments; + * // Check match + * if (v > match_arguments->pattern_length || h > match_arguments->text_length) return 0; + * return (match_arguments->pattern[v] == match_arguments->text[h]); + * } + */ +typedef int (*alignment_match_funct_t)(int,int,void*); + +/* + * Wavefront Sequences + */ +typedef enum { + wf_sequences_ascii = 0, + wf_sequences_lambda = 1, + wf_sequences_packed2bits = 2, +} wf_sequences_mode_t; +typedef struct { + // Mode + wf_sequences_mode_t mode; // Sequences mode + bool reverse; // Reverse sequences + // Current sequences & bounds + char* pattern; // Pointer to current pattern sequence (padded) + char* text; // Pointer to current text sequence (padded) + int pattern_begin; // Pattern begin offset + int pattern_length; // Pattern length + int text_begin; // Text begin offset + int text_length; // Text length + // Lambda Sequence + alignment_match_funct_t match_funct; // Custom matching function (match(v,h,args)) + void* match_funct_arguments; // Generic arguments passed to matching function (args) + // Internal buffers (ASCII encoded) + char* seq_buffer; // Internal buffer + int seq_buffer_allocated; // Internal buffer allocated + char* pattern_buffer; // Source pattern sequence + char* text_buffer; // Source text sequence + int pattern_buffer_length; // Source pattern length + int text_buffer_length; // Source text length + char pattern_eos; // Source pattern char at EOS + char text_eos; // Source pattern char at EOS +} wavefront_sequences_t; + +/* + * Setup + */ +void wavefront_sequences_allocate( + wavefront_sequences_t* const wf_sequences); +void wavefront_sequences_free( + wavefront_sequences_t* const wf_sequences); + +/* + * Init Sequences + */ +void wavefront_sequences_init_ascii( + wavefront_sequences_t* const wf_sequences, + const char* const pattern, + const int pattern_length, + const char* const text, + const int text_length, + const bool reverse); +void wavefront_sequences_init_lambda( + wavefront_sequences_t* const wf_sequences, + alignment_match_funct_t match_funct, + void* match_funct_arguments, + const int pattern_length, + const int text_length, + const bool reverse); +void wavefront_sequences_init_packed2bits( + wavefront_sequences_t* const wf_sequences, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length, + const bool reverse); + + +/* + * Accessors + */ +bool wavefront_sequences_cmp( + wavefront_sequences_t* const wf_sequences, + const int pattern_pos, + const int text_pos); +char wavefront_sequences_get_pattern( + wavefront_sequences_t* const wf_sequences, + const int position); +char wavefront_sequences_get_text( + wavefront_sequences_t* const wf_sequences, + const int position); + +/* + * Resize/Update + */ +void wavefront_sequences_set_bounds( + wavefront_sequences_t* const wf_sequences, + const int pattern_begin, + const int pattern_end, + const int text_begin, + const int text_end); + +#endif /* WAVEFRONT_SEQUENCES_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c new file mode 100644 index 00000000..e9e91bb8 --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.c @@ -0,0 +1,162 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WFA module to check for the termination of an alignment + */ + +#include "wavefront_termination.h" + +/* + * Detect alignment termination (end of alignment) + */ +FORCE_NO_INLINE bool wavefront_termination_end2end( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int score_mod) { + // Parameters + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; + const affine2p_matrix_type component_end = wf_aligner->component_end; + const int alignment_k = DPMATRIX_DIAGONAL(text_length,pattern_length); + const wf_offset_t alignment_offset = DPMATRIX_OFFSET(text_length,pattern_length); + // Select end component + switch (component_end) { + case affine2p_matrix_M: { + // Check diagonal/offset + if (mwavefront->lo > alignment_k || alignment_k > mwavefront->hi) return false; // Not done + const wf_offset_t moffset = mwavefront->offsets[alignment_k]; + if (moffset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_I1: { + // Fetch I1-wavefront & check diagonal/offset + wavefront_t* const i1wavefront = wf_aligner->wf_components.i1wavefronts[score_mod]; + if (i1wavefront == NULL || i1wavefront->lo > alignment_k || alignment_k > i1wavefront->hi) return false; // Not done + const wf_offset_t i1offset = i1wavefront->offsets[alignment_k]; + if (i1offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_I2: { + // Fetch I2-wavefront & check diagonal/offset + wavefront_t* const i2wavefront = wf_aligner->wf_components.i2wavefronts[score_mod]; + if (i2wavefront == NULL || i2wavefront->lo > alignment_k || alignment_k > i2wavefront->hi) return false; // Not done + const wf_offset_t i2offset = i2wavefront->offsets[alignment_k]; + if (i2offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_D1: { + // Fetch D1-wavefront & check diagonal/offset + wavefront_t* const d1wavefront = wf_aligner->wf_components.d1wavefronts[score_mod]; + if (d1wavefront == NULL || d1wavefront->lo > alignment_k || alignment_k > d1wavefront->hi) return false; // Not done + const wf_offset_t d1offset = d1wavefront->offsets[alignment_k]; + if (d1offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + case affine2p_matrix_D2: { + // Fetch D2-wavefront & check diagonal/offset + wavefront_t* const d2wavefront = wf_aligner->wf_components.d2wavefronts[score_mod]; + if (d2wavefront == NULL || d2wavefront->lo > alignment_k || alignment_k > d2wavefront->hi) return false; // Not done + const wf_offset_t d2offset = d2wavefront->offsets[alignment_k]; + if (d2offset < alignment_offset) return false; // Not done + // We are done + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = alignment_k; + wf_aligner->alignment_end_pos.offset = alignment_offset; + return true; + } + default: + break; + } + return false; +} +FORCE_NO_INLINE bool wavefront_termination_endsfree( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int k, + const wf_offset_t offset) { + // Parameters + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; + // Check ends-free reaching boundaries + const int h_pos = WAVEFRONT_H(k,offset); + const int v_pos = WAVEFRONT_V(k,offset); + if (h_pos >= text_length) { // Text is aligned + // Is Pattern end-free? + const int pattern_left = pattern_length - v_pos; + const int pattern_end_free = wf_aligner->alignment_form.pattern_end_free; + if (pattern_left <= pattern_end_free) { + #ifdef WFA_PARALLEL + #pragma omp critical + #endif + { + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = k; + wf_aligner->alignment_end_pos.offset = offset; + } + return true; // Quit (we are done) + } + } + if (v_pos >= pattern_length) { // Pattern is aligned + // Is text end-free? + const int text_left = text_length - h_pos; + const int text_end_free = wf_aligner->alignment_form.text_end_free; + if (text_left <= text_end_free) { + #ifdef WFA_PARALLEL + #pragma omp critical + #endif + { + wf_aligner->alignment_end_pos.score = score; + wf_aligner->alignment_end_pos.k = k; + wf_aligner->alignment_end_pos.offset = offset; + } + return true; // Quit (we are done) + } + } + // Not done + return false; +} diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h new file mode 100644 index 00000000..05085ba8 --- /dev/null +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_termination.h @@ -0,0 +1,57 @@ +/* + * The MIT License + * + * Wavefront Alignment Algorithms + * Copyright (c) 2017 by Santiago Marco-Sola + * + * This file is part of Wavefront Alignment Algorithms. + * + * 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. + * + * PROJECT: Wavefront Alignment Algorithms + * AUTHOR(S): Santiago Marco-Sola + * DESCRIPTION: WFA module to check for the termination of an alignment + */ + +#ifndef WAVEFRONT_TERMINATION_H_ +#define WAVEFRONT_TERMINATION_H_ + +#include "wavefront_aligner.h" + +/* + * Necessary condition for ends-free termination + */ +#define WF_TERMINATION_ENDSFREE(h,v) ((h >= text_length) || (v >= pattern_length)) + +/* + * Detect alignment termination (end of alignment) + */ +bool wavefront_termination_end2end( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int score_mod); +bool wavefront_termination_endsfree( + wavefront_aligner_t* const wf_aligner, + wavefront_t* const mwavefront, + const int score, + const int k, + const wf_offset_t offset); + +#endif /* WAVEFRONT_TERMINATION_H_ */ diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c index 4e733ae9..a696e46e 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.c @@ -48,230 +48,17 @@ #include "wavefront_backtrace.h" #include "wavefront_backtrace_buffer.h" -/* - * Configuration - */ -#define SEQUENCES_PADDING 10 - -/* - * Setup - */ -void wavefront_unialign_status_clear( - wavefront_align_status_t* const align_status) { - align_status->status = WF_STATUS_SUCCESSFUL; - align_status->score = 0; -} -void wavefront_unialigner_system_clear( - wavefront_aligner_t* const wf_aligner) { - // Reset effective limits - wf_aligner->system.max_memory_compact = BUFFER_SIZE_256M; - wf_aligner->system.max_memory_resident = BUFFER_SIZE_256M + BUFFER_SIZE_256M; - switch (wf_aligner->memory_mode) { - case wavefront_memory_med: - wf_aligner->system.max_partial_compacts = 4; - break; - case wavefront_memory_low: - wf_aligner->system.max_partial_compacts = 1; - break; - default: - break; - } - // Profile - timer_reset(&wf_aligner->system.timer); -} -/* - * Resize - */ -void wavefront_unialign_resize( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const bool reverse_sequences) { - // Configure sequences and status - wf_aligner->pattern_length = pattern_length; - wf_aligner->text_length = text_length; - if (wf_aligner->match_funct == NULL) { - if (wf_aligner->sequences != NULL) strings_padded_delete(wf_aligner->sequences); - wf_aligner->sequences = strings_padded_new_rhomb( - pattern,pattern_length,text,text_length, - SEQUENCES_PADDING,reverse_sequences, - wf_aligner->mm_allocator); - wf_aligner->pattern = wf_aligner->sequences->pattern_padded; - wf_aligner->text = wf_aligner->sequences->text_padded; - } else { - wf_aligner->sequences = NULL; - wf_aligner->pattern = NULL; - wf_aligner->text = NULL; - } - wavefront_unialign_status_clear(&wf_aligner->align_status); - // Heuristics clear - wavefront_heuristic_clear(&wf_aligner->heuristic); - // Wavefront components - wavefront_components_resize(&wf_aligner->wf_components, - pattern_length,text_length,&wf_aligner->penalties); - // CIGAR - if (wf_aligner->alignment_scope == compute_alignment) { - cigar_resize(wf_aligner->cigar,2*(pattern_length+text_length)); - } - // Slab - wavefront_slab_clear(wf_aligner->wavefront_slab); - // System - wavefront_unialigner_system_clear(wf_aligner); -} /* * Initialize alignment */ -void wavefront_unialign_initialize_wavefront_m( - wavefront_aligner_t* const wf_aligner, - const int pattern_length, - const int text_length) { - // Parameters - wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; - wavefront_components_t* const wf_components = &wf_aligner->wf_components; - const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; - wavefront_penalties_t* const penalties = &wf_aligner->penalties; - alignment_form_t* const form = &wf_aligner->alignment_form; - // Consider ends-free - const int hi = (penalties->match==0) ? form->text_begin_free : 0; - const int lo = (penalties->match==0) ? -form->pattern_begin_free : 0; - // Compute dimensions - int effective_lo, effective_hi; - wavefront_compute_limits_output(wf_aligner,lo,hi,&effective_lo,&effective_hi); - // Initialize end2end (wavefront zero) - wf_components->mwavefronts[0] = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); - wf_components->mwavefronts[0]->offsets[0] = 0; - wf_components->mwavefronts[0]->lo = lo; - wf_components->mwavefronts[0]->hi = hi; - // Store initial BT-piggypack element - if (wf_components->bt_piggyback) { - const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,0); - wf_components->mwavefronts[0]->bt_pcigar[0] = 0; - wf_components->mwavefronts[0]->bt_prev[0] = block_idx; - } - // Initialize ends-free - if (form->span == alignment_endsfree && penalties->match == 0) { - // Text begin-free - const int text_begin_free = form->text_begin_free; - int h; - for (h=1;h<=text_begin_free;++h) { - const int k = DPMATRIX_DIAGONAL(h,0); - wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(h,0); - if (wf_components->bt_piggyback) { - const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,0,h); - wf_components->mwavefronts[0]->bt_pcigar[k] = 0; - wf_components->mwavefronts[0]->bt_prev[k] = block_idx; - } - } - // Pattern begin-free - const int pattern_begin_free = form->pattern_begin_free; - int v; - for (v=1;v<=pattern_begin_free;++v) { - const int k = DPMATRIX_DIAGONAL(0,v); - wf_components->mwavefronts[0]->offsets[k] = DPMATRIX_OFFSET(0,v); - if (wf_components->bt_piggyback) { - const bt_block_idx_t block_idx = wf_backtrace_buffer_init_block(wf_components->bt_buffer,v,0); - wf_components->mwavefronts[0]->bt_pcigar[k] = 0; - wf_components->mwavefronts[0]->bt_prev[k] = block_idx; - } - } - } - // Nullify unused WFs - if (distance_metric <= gap_linear) return; - wf_components->d1wavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - if (distance_metric==gap_affine) return; - wf_components->d2wavefronts[0] = NULL; - wf_components->i2wavefronts[0] = NULL; -} -void wavefront_unialign_initialize_wavefronts( - wavefront_aligner_t* const wf_aligner, - const int pattern_length, - const int text_length) { - // Parameters - wavefront_slab_t* const wavefront_slab = wf_aligner->wavefront_slab; - wavefront_components_t* const wf_components = &wf_aligner->wf_components; - const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; - // Init wavefronts - if (wf_aligner->component_begin == affine2p_matrix_M) { - // Initialize - wavefront_unialign_initialize_wavefront_m(wf_aligner,pattern_length,text_length); - // Nullify unused WFs - if (distance_metric <= gap_linear) return; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = NULL; - if (distance_metric==gap_affine) return; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = NULL; - } else { - // Compute dimensions - int effective_lo, effective_hi; // Effective lo/hi - wavefront_compute_limits_output(wf_aligner,0,0,&effective_lo,&effective_hi); - wavefront_t* const wavefront = wavefront_slab_allocate(wavefront_slab,effective_lo,effective_hi); - // Initialize - switch (wf_aligner->component_begin) { - case affine2p_matrix_I1: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = wavefront; - wf_components->i1wavefronts[0]->offsets[0] = 0; - wf_components->i1wavefronts[0]->lo = 0; - wf_components->i1wavefronts[0]->hi = 0; - wf_components->d1wavefronts[0] = NULL; - // Nullify unused WFs - if (distance_metric==gap_affine) return; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = NULL; - break; - case affine2p_matrix_I2: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = NULL; - wf_components->i2wavefronts[0] = wavefront; - wf_components->i2wavefronts[0]->offsets[0] = 0; - wf_components->i2wavefronts[0]->lo = 0; - wf_components->i2wavefronts[0]->hi = 0; - wf_components->d2wavefronts[0] = NULL; - break; - case affine2p_matrix_D1: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = wavefront; - wf_components->d1wavefronts[0]->offsets[0] = 0; - wf_components->d1wavefronts[0]->lo = 0; - wf_components->d1wavefronts[0]->hi = 0; - // Nullify unused WFs - if (distance_metric==gap_affine) return; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = NULL; - break; - case affine2p_matrix_D2: - wf_components->mwavefronts[0] = NULL; - wf_components->i1wavefronts[0] = NULL; - wf_components->d1wavefronts[0] = NULL; - wf_components->i2wavefronts[0] = NULL; - wf_components->d2wavefronts[0] = wavefront; - wf_components->d2wavefronts[0]->offsets[0] = 0; - wf_components->d2wavefronts[0]->lo = 0; - wf_components->d2wavefronts[0]->hi = 0; - break; - default: - break; - } - } -} void wavefront_unialign_init( wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end) { // Parameters wavefront_align_status_t* const align_status = &wf_aligner->align_status; - // Resize wavefront aligner - wavefront_unialign_resize(wf_aligner,pattern,pattern_length,text,text_length,false); + alignment_form_t* const alignment_form = &wf_aligner->alignment_form; + const bool end2end = (alignment_form->span == alignment_end2end); // Configure WF-compute function switch (wf_aligner->penalties.distance_metric) { case indel: @@ -293,22 +80,17 @@ void wavefront_unialign_init( break; } // Configure WF-extend function - const bool end2end = (wf_aligner->alignment_form.span == alignment_end2end); - if (wf_aligner->match_funct != NULL) { - align_status->wf_align_extend = &wavefront_extend_custom; - } else if (end2end) { + if (end2end) { align_status->wf_align_extend = &wavefront_extend_end2end; } else { align_status->wf_align_extend = &wavefront_extend_endsfree; } - // Initialize wavefront - wf_aligner->alignment_end_pos.score = -1; // Not aligned - wf_aligner->alignment_end_pos.k = DPMATRIX_DIAGONAL_NULL; + // Initialize wavefront-aligner (to perform a new alignment) wf_aligner->component_begin = component_begin; wf_aligner->component_end = component_end; - wavefront_unialign_initialize_wavefronts(wf_aligner,pattern_length,text_length); - // Plot (WF_0) - if (wf_aligner->plot != NULL) wavefront_plot(wf_aligner,0,0); + wavefront_aligner_init(wf_aligner,0); + // Clear cigar + cigar_clear(wf_aligner->cigar); } /* * Limits @@ -317,9 +99,9 @@ bool wavefront_unialign_reached_limits( wavefront_aligner_t* const wf_aligner, const int score) { // Check alignment-score limit - if (score >= wf_aligner->system.max_alignment_score) { - wf_aligner->cigar->score = wf_aligner->system.max_alignment_score; - wf_aligner->align_status.status = WF_STATUS_MAX_SCORE_REACHED; + if (score >= wf_aligner->system.max_alignment_steps) { + wf_aligner->cigar->score = -wf_aligner->system.max_alignment_steps; + wf_aligner->align_status.status = WF_STATUS_MAX_STEPS_REACHED; wf_aligner->align_status.score = score; return true; // Stop } @@ -366,46 +148,92 @@ void wavefront_unialign_terminate( wavefront_aligner_t* const wf_aligner, const int score) { // Parameters - const int pattern_length = wf_aligner->pattern_length; - const int text_length = wf_aligner->text_length; - // Retrieve alignment + wavefront_align_status_t* const align_status = &wf_aligner->align_status; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; + cigar_t* const cigar = wf_aligner->cigar; + // Select alignment scope + align_status->score = score; if (wf_aligner->alignment_scope == compute_score) { - cigar_clear(wf_aligner->cigar); - wf_aligner->cigar->score = - wavefront_compute_classic_score(wf_aligner,pattern_length,text_length,score); + // Set end-alignment position & score + if (align_status->status == WF_STATUS_END_REACHED) { + cigar->end_v = pattern_length; + cigar->end_h = text_length; + cigar->score = wavefront_compute_classic_score(wf_aligner,pattern_length,text_length,score); + align_status->status = WF_STATUS_ALG_COMPLETED; + } else { + const int k = wf_aligner->alignment_end_pos.k; + const int offset = wf_aligner->alignment_end_pos.offset; + cigar->end_v = WAVEFRONT_V(k,offset); + cigar->end_h = WAVEFRONT_H(k,offset); + cigar->score = wavefront_compute_classic_score(wf_aligner,cigar->end_v,cigar->end_h,score); + align_status->dropped = true; + align_status->status = WF_STATUS_ALG_PARTIAL; + } } else { // Parameters wavefront_components_t* const wf_components = &wf_aligner->wf_components; const int alignment_end_k = wf_aligner->alignment_end_pos.k; const wf_offset_t alignment_end_offset = wf_aligner->alignment_end_pos.offset; - if (wf_components->bt_piggyback) { - // Fetch wavefront - const bool memory_modular = wf_aligner->wf_components.memory_modular; - const int max_score_scope = wf_aligner->wf_components.max_score_scope; - const int score_mod = (memory_modular) ? score % max_score_scope : score; - wavefront_t* const mwavefront = wf_components->mwavefronts[score_mod]; - // Backtrace alignment from buffer (unpacking pcigar) - wavefront_backtrace_pcigar( - wf_aligner,alignment_end_k,alignment_end_offset, - mwavefront->bt_pcigar[alignment_end_k], - mwavefront->bt_prev[alignment_end_k]); + if (alignment_end_offset != WAVEFRONT_OFFSET_NULL) { + if (wf_components->bt_piggyback) { + // Fetch wavefront + const bool memory_modular = wf_aligner->wf_components.memory_modular; + const int max_score_scope = wf_aligner->wf_components.max_score_scope; + const int score_mod = (memory_modular) ? score % max_score_scope : score; + wavefront_t* const mwavefront = wf_components->mwavefronts[score_mod]; + // Backtrace alignment from buffer (unpacking pcigar) + wavefront_backtrace_pcigar( + wf_aligner,alignment_end_k,alignment_end_offset, + mwavefront->bt_pcigar[alignment_end_k], + mwavefront->bt_prev[alignment_end_k]); + } else { + // Backtrace alignment + if (wf_aligner->penalties.distance_metric <= gap_linear) { + wavefront_backtrace_linear(wf_aligner, + score,alignment_end_k,alignment_end_offset); + } else { + wavefront_backtrace_affine(wf_aligner, + wf_aligner->component_begin,wf_aligner->component_end, + score,alignment_end_k,alignment_end_offset); + } + } + } + /* + * Post-processing (Extension-Trim, Score, and Ends) + * + * | Alignment-Regular | Alignment-Extension | + * |------------------------------------------------------------------------------| + * | END_REACHABLE | NoTrim + ALG_COMPLETED | Trim + ALG_PARTIAL|ALG_COMPLETED | + * |END_UNREACHABLE | Trim + ALG_PARTIAL | Trim + ALG_PARTIAL | + */ + const bool do_extension = wf_aligner->alignment_form.extension; + const bool unreachable = (align_status->status == WF_STATUS_END_UNREACHABLE); + align_status->dropped = unreachable; + if (do_extension || unreachable) { + // Alignment extension (maximal score) + const bool cigar_trimmed = wavefront_aligner_maxtrim_cigar(wf_aligner); + if (cigar_trimmed) { + align_status->status = WF_STATUS_ALG_PARTIAL; + } else { + align_status->status = (align_status->status == WF_STATUS_END_UNREACHABLE) ? + WF_STATUS_ALG_PARTIAL : WF_STATUS_ALG_COMPLETED; + } } else { - // Backtrace alignment - if (wf_aligner->penalties.distance_metric <= gap_linear) { - wavefront_backtrace_linear(wf_aligner, - score,alignment_end_k,alignment_end_offset); + const int k = wf_aligner->alignment_end_pos.k; + const int offset = wf_aligner->alignment_end_pos.offset; + cigar->end_v = WAVEFRONT_V(k,offset); + cigar->end_h = WAVEFRONT_H(k,offset); + cigar->score = wavefront_compute_classic_score(wf_aligner,cigar->end_v,cigar->end_h,score); + // Set status + if (unreachable) { + align_status->status = WF_STATUS_ALG_PARTIAL; } else { - wavefront_backtrace_affine(wf_aligner, - wf_aligner->component_begin,wf_aligner->component_end, - score,alignment_end_k,alignment_end_offset); + align_status->status = WF_STATUS_ALG_COMPLETED; } } - // Set score & finish - wf_aligner->cigar->score = - wavefront_compute_classic_score(wf_aligner,pattern_length,text_length,score); } - // Set successful - wf_aligner->align_status.status = WF_STATUS_SUCCESSFUL; } /* * Classic WF-Alignment (Unidirectional) @@ -417,7 +245,6 @@ int wavefront_unialign( void (*wf_align_compute)(wavefront_aligner_t* const,const int) = align_status->wf_align_compute; int (*wf_align_extend)(wavefront_aligner_t* const,const int) = align_status->wf_align_extend; // Compute wavefronts of increasing score - align_status->num_null_steps = 0; int score = align_status->score; while (true) { // Exact extend s-wavefront @@ -425,7 +252,8 @@ int wavefront_unialign( if (finished) { // DEBUG // wavefront_aligner_print(stderr,wf_aligner,0,score,7,0); - if (align_status->status == WF_STATUS_END_REACHED) { + if (align_status->status == WF_STATUS_END_REACHED || + align_status->status == WF_STATUS_END_UNREACHABLE) { wavefront_unialign_terminate(wf_aligner,score); } return align_status->status; @@ -440,10 +268,8 @@ int wavefront_unialign( // DEBUG //wavefront_aligner_print(stderr,wf_aligner,score,score,7,0); } - // Return OK - align_status->score = score; - align_status->status = WF_STATUS_SUCCESSFUL; - return WF_STATUS_SUCCESSFUL; + // Unreachable code + return WF_STATUS_OK; } /* * Display @@ -454,8 +280,11 @@ void wavefront_unialign_print_status( const int score) { // Parameters wavefront_components_t* const wf_components = &wf_aligner->wf_components; + wavefront_sequences_t* const sequences = &wf_aligner->sequences; + const int pattern_length = sequences->pattern_length; + const int text_length = sequences->text_length; // Approximate progress - const int dist_total = MAX(wf_aligner->text_length,wf_aligner->pattern_length); + const int dist_total = MAX(text_length,pattern_length); int s = (wf_components->memory_modular) ? score%wf_components->max_score_scope : score; wavefront_t* wavefront = wf_components->mwavefronts[s]; if (wavefront==NULL && s>0) { @@ -480,11 +309,16 @@ void wavefront_unialign_print_status( const float million_offsets = (wf_len>=0) ? (float)wf_len/1000000.0f : -1.0f; // Print one-line status fprintf(stream,"["); - wavefront_aligner_print_type(stream,wf_aligner); + wavefront_aligner_print_mode(stream,wf_aligner); fprintf(stream, "] SequenceLength=(%d,%d) Score %d (~ %2.3f%% aligned). " "MemoryUsed(WF-Slab,BT-buffer)=(%lu MB,%lu MB). " "Wavefronts ~ %2.3f Moffsets\n", - wf_aligner->pattern_length,wf_aligner->text_length,score,aligned_progress, - CONVERT_B_TO_MB(slab_size),CONVERT_B_TO_MB(bt_buffer_used),million_offsets); + pattern_length, + text_length, + score, + aligned_progress, + CONVERT_B_TO_MB(slab_size), + CONVERT_B_TO_MB(bt_buffer_used), + million_offsets); } diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h index 4c29dbd6..1f92953b 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wavefront_unialign.h @@ -33,30 +33,11 @@ #include "wavefront_aligner.h" -/* - * Resize - */ -void wavefront_unialign_resize( - wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, - const bool reverse_sequences); - /* * Initialize alignment */ -void wavefront_unialign_initialize_wavefronts( - wavefront_aligner_t* const wf_aligner, - const int pattern_length, - const int text_length); void wavefront_unialign_init( wavefront_aligner_t* const wf_aligner, - const char* const pattern, - const int pattern_length, - const char* const text, - const int text_length, const affine2p_matrix_type component_begin, const affine2p_matrix_type component_end); diff --git a/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h b/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h index 1514758a..45379a9f 100644 --- a/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h +++ b/src/common/wflign/deps/WFA2-lib/wavefront/wfa.h @@ -32,28 +32,30 @@ #pragma once #include "system/mm_allocator.h" -#include "utils/string_padded.h" -#include "wavefront_attributes.h" -#include "wavefront_components.h" #include "wavefront_slab.h" #include "wavefront_penalties.h" +#include "wavefront_attributes.h" +#include "wavefront_components.h" +#include "wavefront_sequences.h" #include "wavefront_bialigner.h" - /* * Error codes & messages */ -// Success -#define WF_STATUS_SUCCESSFUL 0 -// Errors -#define WF_STATUS_UNFEASIBLE -1 -#define WF_STATUS_MAX_SCORE_REACHED -2 -#define WF_STATUS_OOM -3 -// Internal -#define WF_STATUS_END_REACHED 1 +// [OK] +#define WF_STATUS_ALG_COMPLETED 0 // Success (Complete alignment found) +#define WF_STATUS_ALG_PARTIAL 1 // Success (Partial alignment found) +// [FAIL] +#define WF_STATUS_MAX_STEPS_REACHED -100 // Maximum number of WFA-steps reached +#define WF_STATUS_OOM -200 // Maximum memory limit reached +#define WF_STATUS_UNATTAINABLE -300 // Alignment unattainable under configured heuristics +// [INTERNAL] +#define WF_STATUS_OK -1 // Computing alignment (in progress) +#define WF_STATUS_END_REACHED -2 // Alignment end reached +#define WF_STATUS_END_UNREACHABLE -3 // Alignment end unreachable under current configuration (eg Z-drop) // Error messages -extern char* wf_error_msg[5]; char* wavefront_align_strerror(const int error_code); +char* wavefront_align_strerror_short(const int error_code); /* * Alignment status @@ -63,6 +65,7 @@ typedef struct { // Status int status; // Status code int score; // Current WF-alignment score + bool dropped; // Heuristically dropped int num_null_steps; // Total contiguous null-steps performed uint64_t memory_used; // Total memory used // Wavefront alignment functions @@ -90,14 +93,7 @@ typedef struct _wavefront_aligner_t { char* align_mode_tag; // WFA mode tag wavefront_align_status_t align_status; // Current alignment status // Sequences - strings_padded_t* sequences; // Padded sequences - char* pattern; // Pattern sequence (padded) - int pattern_length; // Pattern length - char* text; // Text sequence (padded) - int text_length; // Text length - // Custom function to compare sequences - alignment_match_funct_t match_funct; // Custom matching function (match(v,h,args)) - void* match_funct_arguments; // Generic arguments passed to matching function (args) + wavefront_sequences_t sequences; // Input sequences // Alignment Attributes alignment_scope_t alignment_scope; // Alignment scope (score only or full-CIGAR) alignment_form_t alignment_form; // Alignment form (end-to-end/ends-free) @@ -144,6 +140,8 @@ void wavefront_aligner_set_alignment_free_ends( const int pattern_end_free, const int text_begin_free, const int text_end_free); +void wavefront_aligner_set_alignment_extension( + wavefront_aligner_t* const wf_aligner); /* * Heuristic configuration @@ -178,58 +176,41 @@ void wavefront_aligner_set_heuristic_banded_adaptive( const int band_max_k, const int score_steps); -/* - * Match-funct configuration - */ -void wavefront_aligner_set_match_funct( - wavefront_aligner_t* const wf_aligner, - int (*match_funct)(int,int,void*), - void* const match_funct_arguments); - /* * System configuration */ -void wavefront_aligner_set_max_alignment_score( +void wavefront_aligner_set_max_alignment_steps( wavefront_aligner_t* const wf_aligner, - const int max_alignment_score); + const int max_alignment_steps); void wavefront_aligner_set_max_memory( wavefront_aligner_t* const wf_aligner, const uint64_t max_memory_resident, const uint64_t max_memory_abort); void wavefront_aligner_set_max_num_threads( - wavefront_aligner_t* const wf_aligner, - const int max_num_threads); + wavefront_aligner_t* const wf_aligner, + const int max_num_threads); void wavefront_aligner_set_min_offsets_per_thread( - wavefront_aligner_t* const wf_aligner, - const int min_offsets_per_thread); -/* - * Utils - */ -uint64_t wavefront_aligner_get_size( - wavefront_aligner_t* const wf_aligner); - -/* - * Display - */ -void wavefront_aligner_print_type( - FILE* const stream, - wavefront_aligner_t* const wf_aligner); -void wavefront_aligner_print_scope( - FILE* const stream, - wavefront_aligner_t* const wf_aligner); -void wavefront_aligner_print_mode( - FILE* const stream, - wavefront_aligner_t* const wf_aligner); + wavefront_aligner_t* const wf_aligner, + const int min_offsets_per_thread); /* - * Wavefront Alignment + * Wavefront Align */ - int wavefront_align( wavefront_aligner_t* const wf_aligner, const char* const pattern, const int pattern_length, const char* const text, const int text_length); -int wavefront_align_resume( - wavefront_aligner_t* const wf_aligner); +int wavefront_align_lambda( + wavefront_aligner_t* const wf_aligner, + alignment_match_funct_t const match_funct, + void* match_funct_arguments, + const int pattern_length, + const int text_length); +int wavefront_align_packed2bits( + wavefront_aligner_t* const wf_aligner, + const uint8_t* const pattern, + const int pattern_length, + const uint8_t* const text, + const int text_length); diff --git a/src/common/wflign/src/wflign.cpp b/src/common/wflign/src/wflign.cpp index 9ba75f6d..22855fae 100644 --- a/src/common/wflign/src/wflign.cpp +++ b/src/common/wflign/src/wflign.cpp @@ -5,6 +5,7 @@ #include "wflign.hpp" #include "wflign_patch.hpp" + // Namespaces namespace wflign { namespace wavefront { @@ -251,7 +252,7 @@ int wflambda_trace_match( // Retrieve CIGAR char* cigar_ops; int cigar_length; - wflambda_aligner.getAlignmentCigar(&cigar_ops,&cigar_length); + wflambda_aligner.getAlignment(&cigar_ops,&cigar_length); // Traverse CIGAR tracing matches int v = pattern_length-1; int h = text_length-1; @@ -606,11 +607,12 @@ void WFlign::wflign_affine_wavefront( #endif // Align - wflambda_aligner->setMatchFunct(wflambda_extend_match, (void*)&extend_data); - wflambda_aligner->alignEnd2EndLambda(pattern_length,text_length); + wflambda_aligner->alignEnd2End( + wflambda_extend_match, (void*)&extend_data, + pattern_length,text_length); // Extract the trace - if (wflambda_aligner->getAlignmentStatus() == WF_STATUS_SUCCESSFUL) { + if (wflambda_aligner->getAlignmentStatus() == WF_STATUS_OK) { extend_data.num_alignments += wflambda_trace_match( alignments,*wflambda_aligner,trace,pattern_length,text_length); } diff --git a/src/common/wflign/src/wflign_alignment.cpp b/src/common/wflign/src/wflign_alignment.cpp index d5f4efa6..394c44b7 100644 --- a/src/common/wflign/src/wflign_alignment.cpp +++ b/src/common/wflign/src/wflign_alignment.cpp @@ -573,7 +573,7 @@ void wflign_edit_cigar_copy( // Retrieve CIGAR char* cigar_ops; int cigar_length; - wf_aligner.getAlignmentCigar(&cigar_ops,&cigar_length); + wf_aligner.getAlignment(&cigar_ops,&cigar_length); // Allocate cigar_dst->cigar_ops = (char*)malloc(cigar_length); // Copy diff --git a/src/common/wflign/src/wflign_patch.cpp b/src/common/wflign/src/wflign_patch.cpp index 02cdb4a0..93a01586 100644 --- a/src/common/wflign/src/wflign_patch.cpp +++ b/src/common/wflign/src/wflign_patch.cpp @@ -70,7 +70,7 @@ bool do_wfa_segment_alignment( // if it is, we'll align const int max_score = (int)((float)std::max(segment_length_q, segment_length_t) * extend_data->inception_score_max_ratio); - extend_data->wf_aligner->setMaxAlignmentScore(max_score); + extend_data->wf_aligner->setMaxAlignmentSteps(max_score); const int status = extend_data->wf_aligner->alignEnd2End( target + i,segment_length_t, query + j,segment_length_q); @@ -199,9 +199,9 @@ void do_wfa_patch_alignment( = (affine_penalties.gap_opening + (affine_penalties.gap_extension * std::max((int)256, (int)std::min(target_length, query_length)))); - wf_aligner.setMaxAlignmentScore(max_score); + wf_aligner.setMaxAlignmentSteps(max_score); const int status = wf_aligner.alignEnd2End(target + i,target_length,query + j,query_length); - aln.ok = (status == WF_STATUS_SUCCESSFUL); + aln.ok = (status == WF_STATUS_OK); if (aln.ok) { // No more necessary: correct X/M errors in the cigar // hack_cigar(wf_aligner->cigar, query, target, query_length, target_length, j, i); @@ -567,7 +567,7 @@ void write_merged_alignment( char* cigar_ops; int cigar_length; - wf_aligner_heads->getAlignmentCigar(&cigar_ops,&cigar_length); + wf_aligner_heads->getAlignment(&cigar_ops,&cigar_length); for(int xxx = cigar_length - 1; xxx >= 0; --xxx) { //std::cerr << cigar_ops[xxx]; patched.push_back(cigar_ops[xxx]); @@ -1066,7 +1066,7 @@ void write_merged_alignment( char* cigar_ops; int cigar_length; - wf_aligner_tails->getAlignmentCigar(&cigar_ops,&cigar_length); + wf_aligner_tails->getAlignment(&cigar_ops,&cigar_length); for(int xxx = 0; xxx < cigar_length; ++xxx) { //std::cerr << cigar_ops[xxx]; patched.push_back(cigar_ops[xxx]); From 10beb367ec52b202755ba4c1cb6829a6765e937e Mon Sep 17 00:00:00 2001 From: AndreaGuarracino Date: Thu, 15 Jun 2023 14:48:45 +0200 Subject: [PATCH 3/4] to avoid errors on conda --- src/common/wflign/deps/WFA2-lib/system/profiler_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c index eb25853d..623e8b91 100644 --- a/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c +++ b/src/common/wflign/deps/WFA2-lib/system/profiler_timer.c @@ -52,7 +52,7 @@ void timer_get_system_time(struct timespec *ts) { ts->tv_sec = mts.tv_sec; ts->tv_nsec = mts.tv_nsec; #else - clock_gettime(CLOCK_REALTIME,ts); + //clock_gettime(CLOCK_REALTIME,ts); #endif } /* From b0d92b24832a9b839c81966348e0383edc17eacf Mon Sep 17 00:00:00 2001 From: AndreaGuarracino Date: Thu, 15 Jun 2023 21:59:47 +0200 Subject: [PATCH 4/4] fix status code --- src/common/wflign/src/wflign.cpp | 2 +- src/common/wflign/src/wflign_patch.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/wflign/src/wflign.cpp b/src/common/wflign/src/wflign.cpp index 22855fae..1d3a541e 100644 --- a/src/common/wflign/src/wflign.cpp +++ b/src/common/wflign/src/wflign.cpp @@ -612,7 +612,7 @@ void WFlign::wflign_affine_wavefront( pattern_length,text_length); // Extract the trace - if (wflambda_aligner->getAlignmentStatus() == WF_STATUS_OK) { + if (wflambda_aligner->getAlignmentStatus() == WF_STATUS_ALG_COMPLETED) { extend_data.num_alignments += wflambda_trace_match( alignments,*wflambda_aligner,trace,pattern_length,text_length); } diff --git a/src/common/wflign/src/wflign_patch.cpp b/src/common/wflign/src/wflign_patch.cpp index 93a01586..547cd155 100644 --- a/src/common/wflign/src/wflign_patch.cpp +++ b/src/common/wflign/src/wflign_patch.cpp @@ -201,7 +201,7 @@ void do_wfa_patch_alignment( * std::max((int)256, (int)std::min(target_length, query_length)))); wf_aligner.setMaxAlignmentSteps(max_score); const int status = wf_aligner.alignEnd2End(target + i,target_length,query + j,query_length); - aln.ok = (status == WF_STATUS_OK); + aln.ok = (status == WF_STATUS_ALG_COMPLETED); if (aln.ok) { // No more necessary: correct X/M errors in the cigar // hack_cigar(wf_aligner->cigar, query, target, query_length, target_length, j, i);