/* * 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 display and report */ #include "utils/commons.h" #include "system/mm_allocator.h" #include "wavefront_display.h" #include "wavefront_aligner.h" #include "wavefront_compute.h" /* * Constants */ #define WF_DISPLAY_YLABEL_LENGTH 8 /* * Compute dimensions */ int wavefront_display_compute_row_width( const distance_metric_t distance_metric, const int bt_length) { // Compute number of components int num_components = 1; switch (distance_metric) { case indel: case edit: case gap_linear: num_components = 1; break; case gap_affine: num_components = 3; break; case gap_affine_2p: num_components = 5; break; default: break; } // Return return ((num_components)*(4+(bt_length))); } void wavefront_display_compute_limits( wavefront_aligner_t* const wf_aligner, const int score_begin, const int score_end, int* const out_max_k, int* const out_min_k) { // Parameters wavefront_components_t* const wf_components = &wf_aligner->wf_components; const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; // Compute min/max k int i, max_k=INT_MIN, min_k=INT_MAX; for (i=score_begin;i<=score_end;++i) { const int s = (wf_components->memory_modular) ? i%wf_components->max_score_scope : i; wavefront_t* const mwavefront = wf_components->mwavefronts[s]; if (mwavefront != NULL) { max_k = MAX(max_k,mwavefront->hi); min_k = MIN(min_k,mwavefront->lo); } if (distance_metric <= gap_linear) continue; wavefront_t* const i1wavefront = wf_components->i1wavefronts[s]; if (i1wavefront != NULL) { max_k = MAX(max_k,i1wavefront->hi); min_k = MIN(min_k,i1wavefront->lo); } wavefront_t* const d1wavefront = wf_components->d1wavefronts[s]; if (d1wavefront != NULL) { max_k = MAX(max_k,d1wavefront->hi); min_k = MIN(min_k,d1wavefront->lo); } if (distance_metric == gap_affine) continue; wavefront_t* const i2wavefront = wf_components->i2wavefronts[s]; if (i2wavefront != NULL) { max_k = MAX(max_k,i2wavefront->hi); min_k = MIN(min_k,i2wavefront->lo); } wavefront_t* const d2wavefront = wf_components->d2wavefronts[s]; if (d2wavefront != NULL) { max_k = MAX(max_k,d2wavefront->hi); min_k = MIN(min_k,d2wavefront->lo); } } // Return *out_max_k = max_k; *out_min_k = min_k; } /* * Display components */ void wavefront_display_print_element( FILE* const stream, wavefront_aligner_t* const wf_aligner, wavefront_t* const wavefront, const int k, const int bt_length) { // Check limits if (wavefront!=NULL && wavefront->lo <= k && k <= wavefront->hi) { const wf_offset_t offset = wavefront->offsets[k]; if (offset >= 0) { fprintf(stream,"[%2d]",(int)offset); // Print pcigar if (bt_length > 0) { char cigar_buffer[32]; const int pcigar_length = pcigar_unpack(wavefront->bt_pcigar[k],cigar_buffer); const int effective_pcigar_length = MIN(bt_length,pcigar_length); fprintf(stream,"%.*s",effective_pcigar_length,cigar_buffer); PRINT_CHAR_REP(stream,' ',bt_length-effective_pcigar_length); } } else { fprintf(stream,"[ *]"); PRINT_CHAR_REP(stream,' ',bt_length); } } else { PRINT_CHAR_REP(stream,' ',bt_length+4); } } void wavefront_display_print_frame( FILE* const stream, const int score_begin, const int score_end, const int row_width, const int bt_length) { // Align Y-label [k=000] PRINT_CHAR_REP(stream,' ',WF_DISPLAY_YLABEL_LENGTH); // Frame fprintf(stream,"+"); const int num_blocks = score_end-score_begin+1; const int frame_length = (num_blocks*row_width) + (num_blocks-1); PRINT_CHAR_REP(stream,'-',frame_length); fprintf(stream,"+\n"); } void wavefront_display_print_score( FILE* const stream, const int score_begin, const int score_end, const int row_width, const int bt_length) { // Score label PRINT_CHAR_REP(stream,' ',WF_DISPLAY_YLABEL_LENGTH); int s; for (s=score_begin;s<=score_end;++s) { fprintf(stream,"|"); if (row_width >= 10) { PRINT_CHAR_REP(stream,' ',row_width-10); fprintf(stream,"%4d-score",s); } else { fprintf(stream,"s=%2d",s); } } fprintf(stream,"|\n"); } void wavefront_display_print_header_component( FILE* const stream, wavefront_t* const wavefront, char* const wavefront_id, const int bt_length) { fprintf(stream,"[%s]",wavefront_id); if (bt_length > 0) { if (wavefront!=NULL && bt_length >= 10) { PRINT_CHAR_REP(stream,' ',bt_length-10); fprintf(stream,"[|BT|=%2d]",wavefront->bt_occupancy_max); } else { PRINT_CHAR_REP(stream,' ',bt_length-1); } } } void wavefront_display_print_header( FILE* const stream, wavefront_aligner_t* const wf_aligner, const int score_begin, const int score_end, const int bt_length) { // Parameters wavefront_components_t* const wf_components = &wf_aligner->wf_components; const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; const int row_width = wavefront_display_compute_row_width(distance_metric,bt_length); // Score header fprintf(stream,"\n>[SCORE %d-%d]\n",score_begin,score_end); // Frame wavefront_display_print_frame(stream,score_begin,score_end,row_width,bt_length); // Score header wavefront_display_print_score(stream,score_begin,score_end,row_width,bt_length); // Frame wavefront_display_print_frame(stream,score_begin,score_end,row_width,bt_length); // Wavefront labels PRINT_CHAR_REP(stream,' ',WF_DISPLAY_YLABEL_LENGTH); // Align [k= ] int score; for (score=score_begin;score<=score_end;++score) { const int s = (wf_components->memory_modular) ? score%wf_components->max_score_scope : score; fprintf(stream,"|"); wavefront_display_print_header_component(stream,wf_components->mwavefronts[s]," M",bt_length); if (distance_metric <= gap_linear) continue; wavefront_display_print_header_component(stream,wf_components->i1wavefronts[s],"I1",bt_length); wavefront_display_print_header_component(stream,wf_components->d1wavefronts[s],"D1",bt_length); if (distance_metric == gap_affine) continue; wavefront_display_print_header_component(stream,wf_components->i2wavefronts[s],"I2",bt_length); wavefront_display_print_header_component(stream,wf_components->d2wavefronts[s],"D2",bt_length); } fprintf(stream,"|\n"); // Frame wavefront_display_print_frame(stream,score_begin,score_end,row_width,bt_length); } /* * Display */ void wavefront_aligner_print_block( FILE* const stream, wavefront_aligner_t* const wf_aligner, const int score_begin, const int score_end, int bt_length) { // Parameters wavefront_components_t* const wf_components = &wf_aligner->wf_components; const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric; if (!wf_components->bt_piggyback) bt_length = 0; // Check BT // Compute dinmensions int max_k, min_k; wavefront_display_compute_limits(wf_aligner,score_begin,score_end,&max_k,&min_k); // Header wavefront_display_print_header(stream,wf_aligner,score_begin,score_end,bt_length); // Traverse all diagonals int k; for (k=max_k;k>=min_k;k--) { fprintf(stream,"[k=%3d] ",k); // Traverse all scores int i; for (i=score_begin;i<=score_end;++i) { const int s = (wf_components->memory_modular) ? i%wf_components->max_score_scope : i; fprintf(stream,"|"); // Fetch wavefront wavefront_t* const mwavefront = wf_components->mwavefronts[s]; wavefront_display_print_element(stream,wf_aligner,mwavefront,k,bt_length); if (distance_metric <= gap_linear) continue; wavefront_t* const i1wavefront = wf_components->i1wavefronts[s]; wavefront_t* const d1wavefront = wf_components->d1wavefronts[s]; wavefront_display_print_element(stream,wf_aligner,i1wavefront,k,bt_length); wavefront_display_print_element(stream,wf_aligner,d1wavefront,k,bt_length); if (distance_metric == gap_affine) continue; wavefront_t* const i2wavefront = wf_components->i2wavefronts[s]; wavefront_t* const d2wavefront = wf_components->d2wavefronts[s]; wavefront_display_print_element(stream,wf_aligner,i2wavefront,k,bt_length); wavefront_display_print_element(stream,wf_aligner,d2wavefront,k,bt_length); } fprintf(stream,"|\n"); } // Footer const int row_width = wavefront_display_compute_row_width(distance_metric,bt_length); wavefront_display_print_frame(stream,score_begin,score_end,row_width,bt_length); } void wavefront_aligner_print( FILE* const stream, wavefront_aligner_t* const wf_aligner, const int score_begin, const int score_end, const int num_wfs_per_row, const int backtrace_length) { // Print wavefronts by chunks int s; for (s=MAX(score_begin,0);s<=score_end;s+=num_wfs_per_row-1) { const int block_score_end = MIN(s+num_wfs_per_row-1,score_end); wavefront_aligner_print_block(stream,wf_aligner,s,block_score_end,backtrace_length); if (block_score_end == score_end) break; } }