#include "utils/commons.h"
#include "system/mm_allocator.h"
#include "wavefront_plot.h"
#include "wavefront_aligner.h"
void wavefront_plot_heatmaps_allocate(
wavefront_plot_t* const wf_plot,
const int pattern_length,
const int text_length) {
wavefront_plot_attr_t* const attributes = &wf_plot->attributes;
const int resolution_points = attributes->resolution_points;
const int min_v = (wf_plot->min_v == -1) ? 0 : wf_plot->min_v;
const int max_v = (wf_plot->max_v == -1) ? pattern_length-1 : wf_plot->max_v;
const int min_h = (wf_plot->min_h == -1) ? 0 : wf_plot->min_h;
const int max_h = (wf_plot->max_h == -1) ? text_length-1 : wf_plot->max_h;
wf_plot->behavior_heatmap = heatmap_new(heatmap_value,
min_v,max_v,min_h,max_h,resolution_points);
wf_plot->m_heatmap = heatmap_new(heatmap_min,
min_v,max_v,min_h,max_h,resolution_points);
wf_plot->i1_heatmap = NULL;
wf_plot->d1_heatmap = NULL;
wf_plot->i2_heatmap = NULL;
wf_plot->d2_heatmap = NULL;
if (wf_plot->distance_metric < gap_affine) return;
wf_plot->i1_heatmap = heatmap_new(heatmap_min,
min_v,max_v,min_h,max_h,resolution_points);
wf_plot->d1_heatmap = heatmap_new(heatmap_min,
min_v,max_v,min_h,max_h,resolution_points);
if (wf_plot->distance_metric == gap_affine) return;
wf_plot->i2_heatmap = heatmap_new(heatmap_min,
min_v,max_v,min_h,max_h,resolution_points);
wf_plot->d2_heatmap = heatmap_new(heatmap_min,
min_v,max_v,min_h,max_h,resolution_points);
}
void wavefront_plot_heatmaps_free(
wavefront_plot_t* const wf_plot) {
heatmap_delete(wf_plot->behavior_heatmap);
heatmap_delete(wf_plot->m_heatmap);
if (wf_plot->i1_heatmap) heatmap_delete(wf_plot->i1_heatmap);
if (wf_plot->d1_heatmap) heatmap_delete(wf_plot->d1_heatmap);
if (wf_plot->i2_heatmap) heatmap_delete(wf_plot->i2_heatmap);
if (wf_plot->d2_heatmap) heatmap_delete(wf_plot->d2_heatmap);
}
wavefront_plot_t* wavefront_plot_new(
const distance_metric_t distance_metric,
const int pattern_length,
const int text_length,
wavefront_plot_attr_t* const attributes) {
wavefront_plot_t* const wf_plot = (wavefront_plot_t*)malloc(sizeof(wavefront_plot_t));
wf_plot->attributes = *attributes;
wf_plot->distance_metric = distance_metric;
wf_plot->min_v = -1;
wf_plot->max_v = -1;
wf_plot->min_h = -1;
wf_plot->max_h = -1;
wavefront_plot_heatmaps_allocate(wf_plot,pattern_length,text_length);
return wf_plot;
}
void wavefront_plot_resize(
wavefront_plot_t* const wf_plot,
const int pattern_length,
const int text_length) {
wavefront_plot_heatmaps_free(wf_plot);
wavefront_plot_heatmaps_allocate(wf_plot,pattern_length,text_length);
}
void wavefront_plot_delete(
wavefront_plot_t* const wf_plot) {
wavefront_plot_heatmaps_free(wf_plot);
free(wf_plot);
}
void wavefront_plot_component(
wavefront_aligner_t* const wf_aligner,
wavefront_t* const wavefront,
const int score,
heatmap_t* const wf_heatmap,
const bool extend) {
if (wavefront == NULL) return;
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);
int k;
for (k=wavefront->lo;k<=wavefront->hi;++k) {
const wf_offset_t offset = wavefront->offsets[k];
if (offset < 0) continue;
int v_local = WAVEFRONT_V(k,offset);
int h_local = WAVEFRONT_H(k,offset);
if (v_local < 0 || v_local >= pattern_length) continue;
if (h_local < 0 || h_local >= text_length) continue;
int v_global, h_global;
if (reverse) {
v_global = pattern_begin + (pattern_length - 1 - v_local);
h_global = text_begin + (text_length - 1 - h_local);
} else {
v_global = pattern_begin + v_local;
h_global = text_begin + h_local;
}
if (reverse) {
if (h_local>0 && v_local>0) heatmap_set(wf_heatmap,v_global+1,h_global+1,score);
} else {
if (h_local>0 && v_local>0) heatmap_set(wf_heatmap,v_global-1,h_global-1,score);
}
if (extend) {
while (v_local < pattern_length &&
h_local < text_length &&
pattern[v_local] == text[h_local]) {
if (reverse) {
v_global--; h_global--;
} else {
v_global++; h_global++;
}
v_local++; h_local++;
if (reverse) {
heatmap_set(wf_heatmap,v_global+1,h_global+1,score);
} else {
heatmap_set(wf_heatmap,v_global-1,h_global-1,score);
}
}
}
}
}
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 ||
wf_aligner->align_mode == wf_align_biwfa_breakpoint_reverse) {
if (align_level != wf_aligner->plot->attributes.align_level) return;
}
if (wf_aligner->align_mode == wf_align_biwfa_subsidiary &&
wf_aligner->plot->attributes.align_level != -1) return;
const distance_metric_t distance_metric = wf_aligner->penalties.distance_metric;
wavefront_components_t* const wf_components = &wf_aligner->wf_components;
const int score_mod = (wf_components->memory_modular) ? score%wf_components->max_score_scope : score;
wavefront_plot_component(wf_aligner,
wf_components->mwavefronts[score_mod],
score,wf_aligner->plot->m_heatmap,true);
if (distance_metric < gap_affine) return;
wavefront_plot_component(wf_aligner,
wf_components->i1wavefronts[score_mod],
score,wf_aligner->plot->i1_heatmap,false);
wavefront_plot_component(wf_aligner,
wf_components->d1wavefronts[score_mod],
score,wf_aligner->plot->d1_heatmap,false);
if (distance_metric == gap_affine) return;
wavefront_plot_component(wf_aligner,
wf_components->i2wavefronts[score_mod],
score,wf_aligner->plot->i2_heatmap,false);
wavefront_plot_component(wf_aligner,
wf_components->d2wavefronts[score_mod],
score,wf_aligner->plot->d2_heatmap,false);
}
void wavefront_plot_print_cigar(
FILE* const stream,
cigar_t* const cigar,
const char target_operation) {
int i, h=0, v=0, count=0;
for (i=cigar->begin_offset;i<cigar->end_offset;++i) {
const char operation = cigar->operations[i];
switch (operation) {
case 'M': case 'X': ++h; ++v; break;
case 'I': ++h; break;
case 'D': ++v; break;
default: break;
}
if (operation == target_operation && h>0 && v>0) {
if (count++ > 0) fprintf(stream,";");
fprintf(stream,"%d,%d",h-1,v-1);
}
}
}
void wavefront_plot_print(
FILE* const stream,
wavefront_aligner_t* const wf_aligner) {
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;
if (wf_aligner->plot == NULL) {
fprintf(stream,"# WFA-plot not enabled\n");
return;
}
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",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");
fprintf(stream,"# WFAMode ");
wavefront_heuristic_t* const wf_heuristic = &wf_aligner->heuristic;
wavefront_heuristic_print(stream,wf_heuristic);
fprintf(stream,"\n");
fprintf(stream,"# Heatmap M\n"); heatmap_print(stream,wf_plot->m_heatmap);
if (distance_metric == gap_affine) {
fprintf(stream,"# Heatmap I1\n"); heatmap_print(stream,wf_plot->i1_heatmap);
fprintf(stream,"# Heatmap D1\n"); heatmap_print(stream,wf_plot->d1_heatmap);
}
if (distance_metric == gap_affine_2p) {
fprintf(stream,"# Heatmap I2\n"); heatmap_print(stream,wf_plot->i2_heatmap);
fprintf(stream,"# Heatmap D2\n"); heatmap_print(stream,wf_plot->d2_heatmap);
}
fprintf(stream,"# Heatmap Extend\n"); heatmap_print(stream,wf_plot->behavior_heatmap);
if (wf_aligner->alignment_scope == compute_alignment) {
fprintf(stream,"# List CIGAR-M ");
wavefront_plot_print_cigar(stream,wf_aligner->cigar,'M');
fprintf(stream,"\n");
fprintf(stream,"# List CIGAR-X ");
wavefront_plot_print_cigar(stream,wf_aligner->cigar,'X');
fprintf(stream,"\n");
fprintf(stream,"# List CIGAR-I ");
wavefront_plot_print_cigar(stream,wf_aligner->cigar,'I');
fprintf(stream,"\n");
fprintf(stream,"# List CIGAR-D ");
wavefront_plot_print_cigar(stream,wf_aligner->cigar,'D');
fprintf(stream,"\n");
}
}