package SVGManager;

use strict;
use warnings;


sub new {
   my ($class) = @_;
   my $self = {};
   bless $self, $class;
   return $self;
}

my $TEXT_COLOR = "#0A0A0A;";
my $FONT_SIZE = 13;
my $FAMILY_FONT = "san-serif;Verdana;Arial;";
my $BAR_WIDTH = 700;
my $BAR_HIGHT = 40;
my $X_MARGIN = 160;
my $Y_MARGIN = 20;
my %TITLES = (
   # geom score
   emm_mp_clash => 'Clashscore',
   emm_mp_rot_out => 'Rotamer outliers',
   emm_mp_ram_out => 'Rama outliers',
   emm_mp_ram_fv => 'Rama favored',
   emm_cablam_out => 'CaBLAM conf. outliers',
   emm_cablam_ca_out => 'CaBLAM Ca outliers',
   # vs EM Map scores
   emm_smoc => 'SMOC',
   emm_box_cc => 'box CC',
   emm_cc_mask => 'CC(mask)',
   emm_cc_peaks => 'CC(peaks)',
   emm_resol_fsc05 => 'Resol.(FSC=0.5)',
   emm_fsc_avg => 'FSCavg',
   emm_emringer => 'EMringer',
   emm_q_score => 'Q-score',
   emm_q_score_noh => 'Q-score(noH)',
   emm_ai_bb => 'AtomIncl.(BB)',
   # vs Structure (multi)
   multi_gdt_ts => 'GDT_TS(o)',
   multi_gdc_all => 'GDC_ALL(o)',
   multi_qs_lddt => 'LDDT(o)',
   multi_qs_rmsd_ca => 'RMSD(Ca)(o)',
   multi_qs_global => 'QS-score(glob)',
   hb_prec_6 => 'HB Prec.6',
   # vs Structure (mono)
   mono_gdt_ts => 'GDT_TS',
   mono_gdc_all => 'GDC_ALL',
   mono_lddt => 'LDDT',
   mono_rmsd_ca => 'RMSD(Ca)',
   mono_cad => 'CAD',
   mono_qacons => 'DAVIS_QA',
   mono_proq => 'PROQ',
);

sub get_scores{
    my ($self) = @_;
    my @results;
    foreach my $score (qw/emm_mp_clash emm_mp_rot_out emm_mp_ram_out emm_mp_ram_fv emm_cablam_out emm_cablam_ca_out mono_proq emm_smoc emm_box_cc emm_cc_mask emm_cc_peaks emm_resol_fsc05 emm_fsc_avg emm_emringer emm_q_score_noh emm_ai_bb multi_gdt_ts multi_gdc_all multi_qs_lddt multi_qs_rmsd_ca multi_qs_global hb_prec_6 mono_gdt_ts mono_gdc_all mono_lddt mono_rmsd_ca mono_cad mono_qacons/) {
	push @results, {
		SCORE_DB => $score,
		SCORE_NAME => $TITLES{$score},
	}

    }
    return @results;
}

# rhombii at colored bar-scale for a group of scores (e.g. 'vs EM Map Scores', 'vs Structure (multimer)', etc.)
sub generate_SVG{
    my ($self, $ref_data, $flag, $model_red, $model_blue, $title_spec) = @_;
    my $size_x; my $size_y; my $title; my @scores;
    if ($flag eq 'reffree'){
	@scores = qw/emm_mp_clash emm_mp_rot_out emm_mp_ram_out emm_mp_ram_fv emm_cablam_out emm_cablam_ca_out mono_proq/;
	$title = "Reference-free Scores";
    } elsif ($flag eq 'vsmap'){
        @scores = qw/emm_smoc emm_box_cc emm_cc_mask emm_cc_peaks emm_resol_fsc05 emm_fsc_avg emm_emringer emm_q_score_noh emm_ai_bb/;
        $title = "vs EM Map Scores";
    } elsif ($flag eq 'vsstr_multi'){
        @scores = qw/multi_gdt_ts multi_gdc_all multi_qs_lddt multi_qs_rmsd_ca multi_qs_global hb_prec_6/;
        $title = "vs Structure Scores (multimers)";
    } elsif ($flag eq 'vsstr_mono'){
        @scores = qw/mono_gdt_ts mono_gdc_all mono_lddt mono_rmsd_ca mono_cad mono_qacons/;
        $title = "vs Structure Scores (monomers)";
    } elsif (exists $TITLES{$flag}) {
	push @scores, $flag;
	$title = $title_spec;
    }
    $size_x = 2*$X_MARGIN + $BAR_WIDTH; $size_y = $Y_MARGIN + scalar(@scores)*(2*$Y_MARGIN+$BAR_HIGHT);
    my $SVG = sprintf "<svg width=\"%d\" height=\"%d\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", $size_x, $size_y;
    $SVG .= sprintf "<text x=\"%d\" y=\"%d\" text-anchor=\"middle\" alignment-baseline=\"middle\" font-size=\"%d\"  font-weight=\"bold\" font-family=\"$FAMILY_FONT\" fill=\"$TEXT_COLOR\">%s</text>\n", $X_MARGIN+$BAR_WIDTH/2, $Y_MARGIN/2, $FONT_SIZE+1, ($title =~ m/T0101/ ? $TITLES{$flag} : ($title =~ m/T010/ ? '' : $title));
    $SVG .= $self->get_SVG_defs_2();
    my $x_start = $X_MARGIN;
    my $y_start = 2*$Y_MARGIN;
    foreach my $score_name (@scores){
	    $SVG .= $self->draw_scale_box($x_start, $y_start, $BAR_WIDTH, $BAR_HIGHT, $score_name, $ref_data, $model_red, $model_blue, $title);
	    $y_start += 2*$Y_MARGIN+$BAR_HIGHT;
    }
    return $SVG;
}

sub draw_scale_box{
    my ($self, $x, $y, $width, $height,  $score_name, $ref_data, $model_red, $model_blue, $title) = @_;
    if (!defined($width)){
	    $width = 700;
    } 
    if (!defined($height)){
	    $height = 40;
    }
    my $res = '';
    $res .= sprintf "
	<rect class=\"scale\" x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" />
	<polygon points=\"%d,%d %d,%d %d,%d %d,%d\" style=\"fill:none;stroke:grey;stroke-width:1\" />

    ", $x, $y, $width, $height, $x, $y,  ($x+$width), $y, ($x+$width), ($y+$height), $x, ($y+$height);

    # draw labels
    my @labels =$self->get_score_labels($score_name);

    my $x_step = int($width/(scalar(@labels)-1));
    for (my $i = 0; $i < scalar(@labels); $i++){
	    $res .= sprintf "	
	<text x=\"%d\" y=\"%d\" text-anchor=\"middle\" font-size=\"$FONT_SIZE\" font-family=\"$FAMILY_FONT\"  fill=\"$TEXT_COLOR\">%s</text>
	    ",  $x+$i*$x_step, $y-5, $labels[$i];
    }
    $res .= sprintf "
	<text x=\"%d\" y=\"%d\" text-anchor=\"end\" alignment-baseline=\"middle\" font-size=\"$FONT_SIZE\" font-family=\"$FAMILY_FONT\"  %s  fill=\"$TEXT_COLOR\">%s</text>
    ", $x-5, $y+$height/2, ($title =~ m/T010/ ? "font-weight=\"bold\"" : ''), ($title =~ m/T010/ ? $title : $TITLES{$score_name});

    # draw data
    my @data = @{$ref_data};
    my %hash_same_models;
    my $res_blue = ''; my $res_red = '';
    foreach my $el (@data) {
	if ($el->{$score_name} !~ m/^-{0,1}\d+\.{0,1}\d+$/){
	    next;
  	}
	my $key = $el->{$score_name};
	if ($score_name eq 'emm_emringer' && ($key >= 8)){
		$key = ">8.0";
	} else {
		$key = sprintf "%.2f", $key;
	}

	if (! exists $hash_same_models{$key}){
		$hash_same_models{$key} = sprintf "%s:", $key;
	}
	$hash_same_models{$key} .= sprintf ",%s", $el->{MODEL_NAME};
	$hash_same_models{$key} =~ s/:,/:/;
	$res .= $self->draw_single_score($x, $y, $width, $height, $score_name, $el->{$score_name}, $el->{MODEL_NAME}, \%hash_same_models);
	if (defined($model_red) && $model_red eq $el->{MODEL_NAME}){
		$res_red = $self->draw_single_score($x, $y, $width, $height, $score_name, $el->{$score_name}, $el->{MODEL_NAME}, \%hash_same_models, 'red');
	}
	if (defined($model_blue) && $model_blue eq $el->{MODEL_NAME}){
                $res_blue = $self->draw_single_score($x, $y, $width, $height, $score_name, $el->{$score_name}, $el->{MODEL_NAME}, \%hash_same_models, 'blue');
        }
    }
    $res .= $res_blue;
    $res .= $res_red;
    return $res;
}


sub get_score_labels{
    my ($self, $score_name) = @_;
    my @labels;
    if ($score_name eq 'emm_mp_clash')  {
            push @labels, ("worse", "64", "32", "16", "8", "4", "2", "better");
    } elsif ($score_name eq 'emm_cablam_out') {
            push @labels, ("64", "32", "16", "8", "4", "2", "1", "0");
    } elsif ($score_name eq 'emm_cablam_ca_out') {
            push @labels, ("64", "32", "16", "8", "4", "2", "1", "0");
    } elsif ($score_name eq 'emm_mp_ram_out') {
            push @labels, ("64", "32", "16", "8", "4", "2", "1", "0");
    } elsif ($score_name eq 'emm_mp_rot_out') {
            push @labels, ("64", "32", "16", "8", "4", "2", "1", "0");
    } elsif ($score_name eq 'emm_mp_ram_out') {
            push @labels, ("64", "32", "16", "8", "4", "2", "1", "0");
    } elsif ($score_name eq 'emm_mp_ram_fv') {
            push @labels, ("75", "80", "85", "90", "95", "100");
    } elsif ($score_name eq 'emm_smoc'){
            push @labels, ("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9");
    } elsif ($score_name eq 'emm_box_cc'){
            push @labels, ("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9");
    } elsif ($score_name eq 'emm_cc_mask'){
            push @labels, ("0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'emm_cc_peaks'){
            push @labels, ("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9");
    } elsif ($score_name eq 'emm_resol_fsc05'){
            push @labels, ("8", "7", "6", "5", "4", "3", "2", "1", "0");
    } elsif ($score_name eq 'emm_fsc_avg'){
            push @labels, ("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9");
    } elsif ($score_name eq 'emm_emringer') {
	    push @labels, ("0", "1", "2", "3", "4", "5", "6", "7", "8");
    } elsif ($score_name eq 'emm_ai_bb'){
	    push @labels, ("0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'emm_q_score'){
            push @labels, ("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9");
    } elsif ($score_name eq 'emm_q_score_noh'){
            push @labels, ("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9");
    } elsif ($score_name eq 'multi_gdt_ts'){
            push @labels, ("0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100");
    } elsif ($score_name eq 'multi_gdc_all'){
            push @labels, ("0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100");
    } elsif ($score_name eq 'multi_qs_lddt'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'multi_qs_rmsd_ca'){
            push @labels, ("7", "6", "5", "4", "3", "2", "1", "0");
    } elsif ($score_name eq 'multi_qs_global'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'hb_prec_6'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'mono_gdt_ts'){
            push @labels, ("0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100");
    } elsif ($score_name eq 'mono_gdc_all'){
            push @labels, ("0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100");
    } elsif ($score_name eq 'mono_lddt'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'mono_rmsd_ca'){
            push @labels, ("7", "6", "5", "4", "3", "2", "1", "0");
    } elsif ($score_name eq 'mono_cad'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'mono_qacons'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } elsif ($score_name eq 'mono_proq'){
            push @labels, ("0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0");
    } 
    return @labels;
}

sub draw_single_score{
    my ($self, $x_start, $y_start, $width, $height, $score_name, $score_value, $model_name, $ref_hash_same_scores, $color) = @_;
    if ($score_value !~ m/^-{0,1}\d+\.{0,1}\d+$/){
	    return;
    }
    my %hash_same_models = %{$ref_hash_same_scores};
    my $key = $score_value;
    if ($score_name eq 'emm_emringer' && ($score_value >= 8)){
           $key = ">8.0";
    } else {
           $key = sprintf "%.2f", $score_value;
    }
    my $x = $self->calcXposition($x_start, $width, $score_name, $score_value);
    my $res = '';
    if (!defined($color) || ($color ne 'blue' && $color ne 'red') ){
	    $color = "grey";
	    #sand-watches
	    #my $points .= sprintf "%d,%d %d,%d %d,%d %d,%d", $x-5, $y_start, $x+5, $y_start, $x-5, $y_start+$height, $x+5, $y_start+$height;
	    # rhombii
	    my $points .= sprintf "%d,%d %d,%d %d,%d %d,%d", $x, $y_start, $x+5, $y_start+$height/2, $x, $y_start+$height, $x-5, $y_start+$height/2;
	    $res .= sprintf "
	<polygon points=\"%s\" style=\"fill:%s;opacity:0.5;stroke:black;\"><title>%s</title></polygon>
    ", $points, $color, sprintf("%s", $hash_same_models{$key}) ;
    } elsif ($color eq 'blue') {
	     my $points .= sprintf "%d,%d %d,%d %d,%d ", $x-5, $y_start, $x+5, $y_start, $x, $y_start+$height/2 ;
             $res .= sprintf "
        <polygon points=\"%s\" style=\"fill:%s;\"><title>%s</title></polygon>
    ", $points, $color, sprintf("%.3f:%s", $score_value, $model_name);
    } elsif ($color eq 'red') {
             my $points .= sprintf "%d,%d %d,%d %d,%d ", $x, $y_start+$height/2, $x+5, $y_start+$height, $x-5, $y_start+$height ;
             $res .= sprintf "
        <polygon points=\"%s\" style=\"fill:%s;\"><title>%s</title></polygon>
    ", $points, $color, sprintf("%.3f:%s", $score_value, $model_name);
    }
    return $res;
}


sub calcXposition{
    my ($self, $x_start, $width, $score_name, $score_value) = @_;
    my $x;
    if ($score_name eq 'emm_mp_clash') {
        if ($score_value <= 2) {
                $x = $x_start + $width - int($score_value/2*$width/7);
        } elsif ($score_value > 2) {
                $x = $x_start + $width - int(log($score_value)/log(2) * $width/7);
        }
    } elsif ($score_name eq 'emm_cablam_out') {
        if ($score_value <= 1) {
                $x = $x_start + $width - int($score_value*$width/7);
        } elsif ($score_value > 64 ) {
                $x = $x_start;
        } else {
                $x = $x_start + $width - int((1+log($score_value)/log(2)) * $width/7);
        }
    } elsif ($score_name eq 'emm_cablam_ca_out') {
        if ($score_value <= 1) {
                $x = $x_start + $width - int($score_value*$width/7);
        } elsif ($score_value > 64 ) {
                $x = $x_start;
        } else {
                $x = $x_start + $width - int((1+log($score_value)/log(2)) * $width/7);
        }
    } elsif ($score_name eq 'emm_mp_ram_out') {
        if ($score_value <= 1) {
                $x = $x_start + $width - int($score_value/2*$width/7);
        } else {
                $x = $x_start + $width - int(1+log($score_value)/log(2) * $width/7);
        }
    } elsif ($score_name eq 'emm_mp_rot_out') {
        if ($score_value <= 1) {
                $x = $x_start + $width - int($score_value*$width/7);
        } elsif($score_value > 64) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1+log($score_value)/log(2))*$width/7);
        }
    } elsif ($score_name eq 'emm_mp_ram_fv') {
        if ($score_value < 75) {
                $x = $x_start;
        } else {
                $x = $x_start + int(($score_value-75.0)/25.0 * $width);
        }
    } elsif ($score_name eq 'emm_box_cc'){
        if ($score_value > 0.9) {
                $x = $x_start + $width;
        } elsif($score_value < 0.1) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((0.9-$score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_smoc'){
	if ($score_value > 0.9) {
                $x = $x_start + $width;
        } elsif($score_value < 0.1) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((0.9-$score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_cc_mask'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.2) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0-$score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_cc_peaks'){
        if ($score_value > 0.9) {
                $x = $x_start + $width;
        } elsif($score_value < 0.1) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((0.9-$score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_resol_fsc05'){
        if ($score_value <= 0) {
                $x = $x_start + $width;
        } elsif($score_value > 8) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int(($score_value)*$width/8);
        }
    } elsif ($score_name eq 'emm_fsc_avg'){
        if ($score_value > 0.9) {
                $x = $x_start + $width;
        } elsif($score_value < 0.1) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((0.9 - $score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_emringer'){
        if ($score_value > 8) {
                $x = $x_start + $width;
        } elsif($score_value < 0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((8 - $score_value)/8*$width);
        }
    } elsif ($score_name eq 'emm_q_score'){
        if ($score_value > 0.9) {
                $x = $x_start + $width;
        } elsif($score_value < 0.1) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((0.9 - $score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_q_score_noh'){
        if ($score_value > 0.9) {
                $x = $x_start + $width;
        } elsif($score_value < 0.1) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((0.9 - $score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'emm_ai_bb'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.2) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/0.8*$width);
        }
    } elsif ($score_name eq 'multi_gdt_ts'){
        if ($score_value > 100) {
                $x = $x_start + $width;
        } elsif($score_value < 0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((100 - $score_value)/100*$width);
        }
    } elsif ($score_name eq 'multi_gdc_all'){
        if ($score_value > 100) {
                $x = $x_start + $width;
        } elsif($score_value < 0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((100 - $score_value)/100*$width);
        }
    } elsif ($score_name eq 'multi_qs_lddt'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    } elsif ($score_name eq 'multi_qs_rmsd_ca'){
        if ($score_value <= 0) {
                $x = $x_start + $width;
        } elsif($score_value > 7) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int(($score_value)*$width/7);
        }
    } elsif ($score_name eq 'multi_qs_global'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    } elsif ($score_name eq 'hb_prec_6'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    } elsif ($score_name eq 'mono_gdt_ts'){
        if ($score_value > 100) {
                $x = $x_start + $width;
        } elsif($score_value < 0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((100 - $score_value)/100*$width);
        }
    } elsif ($score_name eq 'mono_gdc_all'){
        if ($score_value > 100) {
                $x = $x_start + $width;
        } elsif($score_value < 0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((100 - $score_value)/100*$width);
        }
    } elsif ($score_name eq 'mono_lddt'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    } elsif ($score_name eq 'mono_rmsd_ca'){
        if ($score_value <= 0) {
                $x = $x_start + $width;
        } elsif($score_value > 7) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int(($score_value)*$width/7);
        }
    } elsif ($score_name eq 'mono_cad'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    } elsif ($score_name eq 'mono_qacons'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    } elsif ($score_name eq 'mono_proq'){
        if ($score_value > 1.0) {
                $x = $x_start + $width;
        } elsif($score_value < 0.0) {
                $x = $x_start ;
        } else {
                $x = $x_start + $width - int((1.0 - $score_value)/1.0*$width);
        }
    }
    return $x;
}

sub get_SVG_defs{
    my ($self) = @_;
    my $res = '
  <defs>
      <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="59%"/>
        <stop class="stop3" offset="85.7%"/>
        <stop class="stop4" offset="100%"/>
      </linearGradient>
      <style type="text/css"><![CDATA[
        .scale { fill: url(#Gradient1); }
        .stop1 { stop-color: #DD710C; }
        .stop2 { stop-color: white; stop-opacity: 1.0; }
        .stop3 { stop-color: #2EC2DD; }
        .stop4 { stop-color: white; stop-opacity: 1.0;}
      ]]></style>
  </defs>';
  return $res;
}

# two gradient colors
sub get_SVG_defs_2{
    my ($self) = @_;
    my $res = '
  <defs>
      <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="50%"/>
        <stop class="stop3" offset="100%"/>
      </linearGradient>
      <style type="text/css"><![CDATA[
        .scale { fill: url(#Gradient1); }
        .stop1 { stop-color: #DD710C; }
        .stop2 { stop-color: white; stop-opacity: 1.0; }
        .stop3 { stop-color: #00CC00; }
      ]]></style>
  </defs>';
  return $res;
}




# colored bars
sub get_alignment_bar{
    my ($self, $ref_hash_align_data, $start, $end, $metric) = @_;
    my %align_data = %{$ref_hash_align_data};
    my $align_data_count = $end - $start + 1;
    my $step = 1;
    if ($align_data_count <= 100){
        $step = 5;
    } elsif ($align_data_count <= 200){
        $step = 4;
    } elsif ($align_data_count <= 250){
        $step = 3;
    } elsif ($align_data_count <= 400){
        $step = 2;
    } else {
        $step = 1;
    }
    if($align_data_count == 0) { return; }
    my $color_white     = '#ffffff';
    my $color_black     = '#000000';
    my $color_blue      = '#00b8ff';
    my $color_darkblue  = '#0000c8';
    my $color_sky       = '#00fffa';
    my $color_yellow    = '#ffff00';
    my $color_green     = '#00ff00';
    my $color_orange    = '#ff9900';
    my $color_red       = '#ff6900';
    my $color_darkred   = '#ff0000';
    my $color_grey      = '#f0f0f0';
    my $color_magenta   = '#cc33cc';
    my $height = 10;
    my $width = $align_data_count*$step;
    my $result = sprintf "<svg width=\"%spt\" height=\"%spt\">\n", $width, $height;
    for(my $i = 0; $i < $align_data_count; $i++){
        my $color = $color_white;
	my $res = $i + $start;
	if (exists $align_data{$res} ){
		if ($metric ne 'gdt_ts'){#'lddt' || $metric eq 'proq' || $metric eq 'qmean' || $metric eq 'qacons' || $metric eq 'tempy' || $metric eq 'atomincl'){
			if ($align_data{$res} >= 0.8) {
	                   $color = $color_sky;
	                } elsif ($align_data{$res} >= 0.6) {
        	           $color = $color_green;
	                } elsif ($align_data{$res} >= 0.4) {
        	           $color = $color_yellow;
	                } elsif ($align_data{$res} >= 0.2) {
                	   $color = $color_orange;
        	        } else {
	                   $color = $color_darkred;
                	}
		} elsif ($metric eq 'gdt_ts'){
                	if ($align_data{$res} <= 1.0) {
	                   $color = $color_sky;
	                } elsif ($align_data{$res} <= 2.0) {
	                   $color = $color_green;
	                } elsif ($align_data{$res} <= 4.0) {
	                   $color = $color_yellow;
	                } elsif ($align_data{$res} <= 8.0) {
	                   $color = $color_orange;
	                } else {
	                   $color = $color_darkred;
               		}
        	}
        }
	my $x = ($res-$start)*$step;
        $result .= sprintf "<g><title>%s:%s</title>\n", $res, (exists $align_data{$res} ?  sprintf("%.2f", $align_data{$res}) : '');
        $result .= sprintf "<rect x=\"%spt\" y=\"0pt\" width=\"%spt\" height=\"%spt\" fill=\"%s\"/>\n", $x, $step, $height, $color;
        $result .= sprintf "</g>\n";
    }
    $result .= "</svg>";
    return $result;
}

sub get_scale_bar {
    my ($self, $start, $end) = @_;
    my $target_size = $end - $start + 1;
    my $step = 1;
    my $incr = 50;
    if ($target_size <= 100) {
            $step = 5;
            $incr = 10;
    } elsif ($target_size <= 200){
            $step = 4;
            $incr = 20;
    } elsif ($target_size <= 250){
            $step = 3;
            $incr = 20;
    } elsif ($target_size <= 400){
            $step = 2;
            $incr = 40;
    } else {
            $step = 1;
            $incr = 50;
    }
    my $height = 10;
    my $width = $target_size*$step;
    my $result = sprintf "<svg width=\"%spt\" height=\"%spt\" fill=\"white\">\n", $width, $height;
    for (my $i = $start; $i <= $end; $i++){
        if ($i % 10 == 0) {
                $result .= sprintf "<line x1=\"%dpt\" y1=\"%dpt\" x2=\"%dpt\" y2=\"%dpt\" stroke=\"gray\"/>\n", ($i-$start)*$step + 0.5*$step, $height, ($i-$start)*$step + 0.5*$step, 0.6*$height;
        }
        if ($i % $incr == 0) {
                $result .= sprintf "<text x=\"%dpt\" y=\"%dpt\" fill=\"gray\" font-family=\"Arial,Verdana,Helvetica,Sans-serif\" font-size=\"10\">%s</text>\n", ($i-$start)*$step + 4, 0.8*$height, $i;
        }
    }
    $result .= sprintf "</svg>\n";
    return $result;
}

1;
