package ImagesManager;

use strict;
use warnings;

use GD;

use lib qw(Core);

use Configuration;
use Logger;

use TargetsManager;
use GroupsManager;
use ResultsManager;
use String;


my $DEFAULT_FONT = '/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf';
my $DEFAULT_SMALL_FONT = '/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold.ttf';
my $DEFAULT_TOP_FONT = '/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf';
my $DEFAULT_AXIS_FONT = '/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold.ttf';

sub new {
    my ($class, $debug) = @_;
    
    my $self = {
        _database => Database->new($CONFIG->{HOSTNAME}, $CONFIG->{PORT}, $CONFIG->{DATABASE}, $CONFIG->{USERNAME}, $CONFIG->{PASSWORD}),
        _logger => Logger->new()
    };
    
    # by default debug mode is turned on
    $self->{_debug} = !defined($debug) ? 1 : $debug;
    
    $self->{_logger}->set_error_log('error.log');
    
    bless $self, $class;
    return $self;
}

# highlight_type can be {show_related, or compare_groups, or not defined value}
# filter:
#   for show_related $filter_params is hash {group, model}
#   for compare_groups $filter_params is array of groups
sub generate_gdt_image {
    my ($self, $target, $gdt_data, $output_file_path, $view_first_only, $highlight_type, $filter_params, $map_url_params) = @_;
    
    my $image = new GD::Image(680, 440);
    
    my $white = $image->colorAllocate(255, 255, 255);
    my $black = $image->colorAllocate(0, 0, 0);
    
    my $red = $image->colorAllocate(255, 0, 0);
    my $darkred = $image->colorAllocate(128, 0, 0);
    my $green = $image->colorAllocate(0, 128, 0);
    my $darkgreen = $image->colorAllocate(0, 64, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    my $grey = $image->colorAllocate(204, 204, 204);
    my $blue = $image->colorAllocate(0, 0, 255 );
    my $darkblue = $image->colorAllocate(0, 0, 200 );
    my $darkgrey = $image->colorAllocate(100, 100, 100);
    my $purple = $image->colorAllocate(200, 0, 255);
    my $orange = $image->colorAllocate(255, 128, 0);
    my $whiteblue = $image->colorAllocate(100, 200, 255);
    my $rose = $image->colorAllocate(255,100,80);
    my $darkpurple = $image->colorAllocate(150, 0, 200);
    my $darkyellow = $image->colorAllocate(200, 200, 0);
    my $pink = $image->colorAllocate(255, 0, 255);
    my $aqua = $image->colorAllocate(0, 255, 255);

	my @model_color = (
#		[$red, $darkred],
		[$pink, $pink],
#		[$green, $darkgreen],
		[$aqua, $aqua],
#		[$blue, $darkblue],
		[$darkgrey, $darkgrey],
	);
    
    #$image->transparent($white);
    $image->interlaced('true');
    
    $image->setThickness(1);
    
    # draw axes
    $image->line(65, 65, 615, 65, $black); # top
    $image->line(65, 375, 615, 375, $black); # bottom
    $image->line(65, 65, 65, 375, $black); # left
    $image->line(615, 65, 615, 375, $black); # right
    
    # draw ruler
    for(my $i = 0; $i < 10; $i++) {
        $image->line(65, 75 + 29*$i, 65 + (($i % 5 == 0) ? 10 : 5), 75 + 29*$i, $black); # left
        $image->line(605 + (($i % 5 == 0) ? 0 : 5), 75 + 29*$i, 615, 75 + 29*$i, $black); # right
        $image->line(75 + 53*($i + 1), 65, 75 + 53*($i + 1), 65 + ((($i + 1) % 2 == 0) ? 10 : 5), $black); # top
        $image->line(75 + 53*($i + 1), 365 + ((($i + 1) % 2 == 0) ? 0 : 5), 75 + 53*($i + 1), 375, $black); # bottom
    }

    # draw titles
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 220, 420, "Percent of Residues (CA)");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 3.14 / 2, 30, 320, "Distance Cutoff, A");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 310, 30, $target);
    
    # draw axes rules X
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0,  60, 395, "0");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 171, 395, "20");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 277, 395, "40");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 383, 395, "60");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 489, 395, "80");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 0, 595, 395, "100");

    # draw axes rules Y
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 3.14 / 2, 55, 380, "0");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 3.14 / 2, 55, 225, "5");
    $image->stringFT($black, $DEFAULT_SMALL_FONT, 12, 3.14 / 2, 55,  75, "10");
    
    my $map_string = '';
    
    my $step = 530 / 100;
    for(my $i = 0; $i < scalar(@{$gdt_data}); $i++) {
        if($view_first_only && $gdt_data->[$i]->{MODEL} != 1) { next; }
        #if($gdt_data->[$i]->{CODE} != 164) { next; } # for test purposes
        
        my @percentage = split(/\s+/, $gdt_data->[$i]->{GDT_CA_PERCENTAGE_4});
        my $percentage_count = scalar(@percentage);
        
        if($percentage_count < 20) { next; } # skip invalid gdt percentage files
        
        #PLEASE! please please! use standard model name function generation!
        #my $model_name = sprintf("%s%s%s_%d", $gdt_data->[$i]->{TARGET}, $gdt_data->[$i]->{PFRMAT}, $gdt_data->[$i]->{CODE}, $gdt_data->[$i]->{MODEL});
        my $r_m = new ResultsManager();        
        my $model_name = $r_m->build_model_name($gdt_data->[$i]->{TARGET}, $gdt_data->[$i]->{PFRMAT}, $gdt_data->[$i]->{CODE}, $gdt_data->[$i]->{MODEL},$gdt_data->[$i]->{PARENT}, $gdt_data->[$i]->{DOMAIN});
        
        
        $map_string .= sprintf('<area href="?%s&model=%s" onmouseover="title=\'%s\';self.status=\'%s\';return false" onmouseout="self.status=\'\';return false" shape="poly" coords="', $map_url_params, $model_name, $model_name, $model_name);
        
        for(my $j = 0; $j < $percentage_count - 1; $j++) {
            $image->line(75 + $percentage[$j] * $step, 365 - 15*$j, 75 + $percentage[$j + 1] * $step, 365 - 15*($j + 1), $orange);
            
            $map_string .= sprintf('%d,%d,', 75 + $percentage[$j] * $step + 1, 365 - 15*$j + 1); # -1 and +1 - to make polygon wider - easier to click
        }
        $map_string .= sprintf('%d,%d,', 75 + $percentage[$percentage_count - 1] * $step, 365 - 15*($percentage_count - 1));
        
        # the second loop only for map logic to build correct polygon with width 3
        for(my $j = $percentage_count - 1; $j > 0; $j--) {
            $map_string .= sprintf('%d,%d,', 75 + $percentage[$j] * $step - 1, 365 - 15*$j - 1); # -1 and +1 - to make polygon wider - easier to click
        }
        $map_string .= sprintf("%d,%d\">\n", 75 + $percentage[0] * $step, 365);
    }
    
    if(open(MAP_FILE, sprintf("> %s.js", $output_file_path))) {
        print(MAP_FILE $map_string);
        close(MAP_FILE);
    }
    
    $image->setThickness(2);
    for(my $i = 0; $i < scalar(@{$gdt_data}); $i++) {
        if($view_first_only && $gdt_data->[$i]->{MODEL} != 1) { next; }
        
        my @percentage = split(/\s+/, $gdt_data->[$i]->{GDT_CA_PERCENTAGE_4});
        my $percentage_count = scalar(@percentage);
        
        if($percentage_count < 20) { next; } # skip invalid gdt percentage files
        
        my $color = $orange;
        if(defined($highlight_type) && ($highlight_type eq 'show_related_small') || ($highlight_type eq 'show_related') || ($highlight_type eq 'compare_groups')) {
            if((($highlight_type eq 'show_related') ||($highlight_type eq 'show_related_small')) && ($filter_params->{GROUP}) && ($filter_params->{GROUP} == $gdt_data->[$i]->{CODE})) {
                if($gdt_data->[$i]->{MODEL} == $filter_params->{MODEL}) {
                    $color = $blue;
                } else {
                    $color = $black;
                }
                
                for(my $j = 0; $j < scalar(@percentage) - 1; $j++) {
                    $image->line(75 + $percentage[$j] * $step, 365 - 15*$j, 75 + $percentage[$j + 1] * $step, 365 - 15*($j + 1), $color);
                }
            }
            
            if($highlight_type eq 'compare_groups') {
                my $highlight = 0;
                for(my $z = 0; $z < scalar(@{$filter_params}); $z++) {
                    if($filter_params->[$z] == $gdt_data->[$i]->{GROUP_ID}) {
						$color = $model_color[$z][$gdt_data->[$i]->{MODEL} != 1];
                        $highlight = 1;
                    }
                }
                
                if($highlight) {
                    for(my $j = 0; $j < scalar(@percentage) - 1; $j++) {
                        $image->line(75 + $percentage[$j] * $step, 365 - 15*$j, 75 + $percentage[$j + 1] * $step, 365 - 15*($j + 1), $color);
                    }
                }
                $highlight = 0;
            }
        }
    }
    
    binmode STDOUT;
    
    my $image_path = $output_file_path;
    
    if (open FILE, "+>", $image_path) {
        print FILE $image->png;
        close(FILE);
    }
    
    # make small pictures
    if(!defined($highlight_type) || ($highlight_type eq '') || ($highlight_type eq 'show_related_small')) {
        my $small_image_path = $output_file_path;
        $small_image_path =~ s/.png/.small.png/g;        
        $self->resize($output_file_path, $small_image_path, 140, 100);
        if($highlight_type eq 'show_related_small') {
            system(sprintf("rm -f %s ",$output_file_path));            
            system(sprintf("rm -f %s.js ",$output_file_path));
        }
    }
    
    return;
}

sub generate_eqv_image {
    my ($self, $eqv_data, $output_file_path) = @_;
    
    my $width = 500;
    my $height = 8;
    
    my $image = new GD::Image($width, $height);
    
    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    
    $image->transparent($white);
    $image->interlaced('true');
    
    my @eqv_data = split(/ /, $eqv_data);
    my $eqv_data_count = scalar(@eqv_data);
    
    if($eqv_data_count == 0) { return; }
    
    $image->filledRectangle(0, 0, $width, $height, $white);
    
    my $step = int($width / $eqv_data_count);
    for(my $i = 0; $i < $eqv_data_count; $i++) {
        my $color = $white;
        if ($eqv_data[$i] == 1) {
            $color = $red;
        } elsif ($eqv_data[$i] == 2) {
            $color = $yellow;
        } elsif ($eqv_data[$i] == 3) {
            $color = $green;
        }
        
        $image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);
    }
    
    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }
    
    return;
}


sub generate_eqv_image_varwidth {
    my ($self, $eqv_data, $output_file_path) = @_;
    $eqv_data=defined($eqv_data) ? $eqv_data:'';
    my @eqv_data = split(/ /, $eqv_data);
    my $eqv_data_count = scalar(@eqv_data);
    my $step = 1;
    if ($eqv_data_count <= 100){
	$step = 5;
    } elsif ($eqv_data_count <= 200){
	$step = 4;
    } elsif ($eqv_data_count <= 250){
	$step = 3; 
    } elsif ($eqv_data_count <= 400){
	$step = 2; 
    } else {
	$step = 1;
    }

    if($eqv_data_count == 0) { return; }


    my $width = $eqv_data_count * $step;
    my $height = 10;

    my $image = new GD::Image($width, $height);

    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);

    $image->transparent($white);
    $image->interlaced('true');

    $image->filledRectangle(0, 0, $width, $height, $white);

    for(my $i = 0; $i < $eqv_data_count; $i++) {
        my $color = $white;
        if ($eqv_data[$i] == 1) {
            $color = $red;
        } elsif ($eqv_data[$i] == 2) {
            $color = $yellow;
        } elsif ($eqv_data[$i] == 3) {
            $color = $green;
        }

        $image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);
    }

    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }

    return;
}


sub generate_caca_diffs_bar_varwidth {
    my ($self, $ref_align_data, $output_file_path) = @_;
    my @align_data = @{$ref_align_data};
    my $align_data_count = scalar(@align_data);
    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 $width = $align_data_count * $step;
    my $height = 10;

    my $image = new GD::Image($width, $height);

    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);

    my $color_white     = $image->colorAllocate(255, 255, 255);
    my $color_black     = $image->colorAllocate(0, 0, 0);
    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 153, 0); #ff9900
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000
    my $color_grey      = $image->colorAllocate(204, 204, 204);
    my $color_magenta   = $image->colorAllocate(204,51,204); #cc33cc
    

    $image->transparent($color_white);
    $image->interlaced('true');

    $image->filledRectangle(0, 0, $width, $height, $color_white);

    for(my $i = 0; $i < $align_data_count; $i++) {
        my $color = $color_white;
	if ($align_data[$i] ne 'X'){
	 if ($align_data[$i] >= 0.0){
	   if ($align_data[$i] <= 1.0 ) {
             $color = $color_sky;
           } elsif ($align_data[$i] <= 2.0) {
             $color = $color_green;
           } elsif ($align_data[$i]<= 4.0) {
             $color = $color_yellow;
           } elsif ($align_data[$i] <= 8.0){
	     $color = $color_orange; 
           } elsif ($align_data[$i] > 8.0){
	     $color = $color_darkred;
           }
	 }
        }
        $image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);
    }

    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }

    return;
}

# bar of difference of CA-CA distances in pair (T0_model - Target) - (Tc_model - Target)
sub generate_caca_dist_diffs_bar_varwidth {
    my ($self, $ref_align_data, $output_file_path) = @_;
    my @align_data = @{$ref_align_data};
    my $align_data_count = scalar(@align_data);
    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 $width = $align_data_count * $step;
    my $height = 10;

    my $image = new GD::Image($width, $height);

    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);

    my $color_white     = $image->colorAllocate(255, 255, 255);
    my $color_black     = $image->colorAllocate(0, 0, 0);
    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 153, 0); #ff9900
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000
    my $color_grey      = $image->colorAllocate(204, 204, 204);
    my $color_magenta   = $image->colorAllocate(204,51,204); #cc33cc

    $image->transparent($color_white);
    $image->interlaced('true');

    $image->filledRectangle(0, 0, $width, $height, $color_white);

    for(my $i = 0; $i < $align_data_count; $i++) {
        my $color = $color_white;
        if ($align_data[$i] ne 'X'){
         
           if ($align_data[$i] <= -5.0 ) {
             $color = $color_darkblue;
           } elsif ($align_data[$i] <= -2.0) {
             $color = $color_sky;
           } elsif ($align_data[$i]<= -0.5) {
             $color = $color_green;
           } elsif ($align_data[$i] <= 0.5){
             $color = $color_yellow;
           } elsif ($align_data[$i] <= 2.0){ 
             $color = $color_orange;
           } elsif ($align_data[$i] <= 5.0){
             $color = $color_red;
           } elsif ($align_data[$i] > 5.0) {
	     $color = $color_darkred;
	   }
         
        }
        $image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);
    }

    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }

    return;
}



sub generate_al_image {
    my ($self, $al0, $al4, $al4x, $nt, $output_file_path) = @_;
    
    my $width = 500;
    my $height = 8;
    
    my $image = new GD::Image($width, $height);
    
    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    
    $image->transparent($white);
    $image->interlaced('true');
    
    $image->filledRectangle(0, 0, $width, $height, $white);
    
    if($nt == 0) { return; }
    
    $image->filledRectangle(0, 1, $width * $al4x / $nt, $height - 1, $red);
    $image->filledRectangle(0, 1, $width * $al4 / $nt, $height - 1, $yellow);
    $image->filledRectangle(0, 1, $width * $al0 / $nt, $height - 1, $green);
    
    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }
    
    return;
}


sub generate_al_small_image {
    my ($self, $target_name, $output_file_path, $highlite_group_code, @results) = @_;
    
    my $results_count = scalar(@results);
    
    my $width = 60;
    my $height_part = 1;
    my $height = (($results_count>0)?($results_count*$height_part):74);
    
    
    my $image = new GD::Image($width, $height);
    
    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    my $black = $image->colorAllocate(0, 0, 0);
    
    $image->transparent($white);
    $image->interlaced('true');
    
    $image->filledRectangle(0, 0, $width, $height, $white);
    
    if (open FILE, "+>", $output_file_path) {
        for(my $i = 0; $i < $results_count; $i++) {
            if($results[$i]->{N2_5} == 0) {
            } elsif(defined($highlite_group_code) && $results[$i]->{CODE} eq $highlite_group_code) {
                $image->filledRectangle(0, $i-2 * $height_part, $width, $i+4*$height_part , $black);
                $i = $i +4;                
            } else {
                $image->filledRectangle(0, $i * $height_part, $width * $results[$i]->{AL4X} / $results[$i]->{N2_5}, $i*$height_part , $red);
                $image->filledRectangle(0, $i * $height_part, $width * $results[$i]->{AL4}  / $results[$i]->{N2_5}, $i*$height_part, $yellow);
                $image->filledRectangle(0, $i * $height_part, $width * $results[$i]->{AL0}  / $results[$i]->{N2_5}, $i*$height_part, $green);
                
            }
        }
        print FILE $image->png;
        close(FILE);
    }
    #$self->resize($output_file_path, $output_file_path, 60, 74); #This resize function set size proportionaly by old W and H but we need custom
    return;
}


sub protein_image {
    my ($self, $input_pdb_file, $output_png_file, $width, $height) = @_;
    
    my $result = 0;
    
    # fix coresponding to OS, this is for ciemniak
    my $PATH_TO_MOLAUTO = '/usr/local/molscript-2.1.2/molauto';
    my $PATH_TO_MOLSCRIPT = '/usr/local/molscript-2.1.2/molscript';
    my $PATH_TO_RASTER3D_RENDER = '/usr/lib/raster3d/render.real';
    
    # /usr/local/molscript-2.1.2/molauto /shared/bystra/data/CASP9/TARGETS/T0387.pdb | /usr/local/molscript-2.1.2/molscript -accum 66 -raster3d 3 -size 500 500 | /usr/lib/raster3d/render.real -size 500x500 -quality 100 -png /home/zenyk/1.png
    # [pdb] -> molauto -> molscript -> render.real -> [png]
    if(system(sprintf("%s %s | %s -raster3d 3 -size %d %d | %s -size %dx%d -quality 100 -png %s"
        , $PATH_TO_MOLAUTO
        , $input_pdb_file
        , $PATH_TO_MOLSCRIPT
        , $width
        , $height
        , $PATH_TO_RASTER3D_RENDER
        , $width
        , $height
        , $output_png_file)) == 0) {
        $result = 1;
    }
    
    return $result;
}

sub resize {
    my ($self, $input_file, $output_file, $new_width, $new_height) = @_;
    
    my $result = 0;
    
    if(system(sprintf("/usr/bin/convert %s -resize %dx%d %s", $input_file, $new_width, $new_height, $output_file)) == 0) {
        $result = 1;
    }
    
    return $result;
}

sub log {
    my ($self, $message) = @_;
    
    $self->{_logger}->error("ImagesManager.pm", $message);
    
    return;
}

sub draw_refined_distances_plot {
    my ($self, $correct_target_name, $start_model, $refined_model,$ranges) = @_;

    my $TOP_TITLE = 'Target ' . $correct_target_name;
    my $BOTTOM_TITLE = 'Residue';
    my $LEFT_TITLE = 'CA-CA difference, A';
    my $FONT_SIZE = 10; 

    my $DEFAULT_WIDTH = 800;
    my $DEFAULT_HEIGHT = 300;
    my $LEFT_MARGIN = 50;
    my $RIGHT_MARGIN = 140;
    my $TOP_MARGIN = 30;
    my $BOTTOM_MARGIN = 40;

    #my ($target_size) = $$ranges[scalar(@$ranges) - 1];
    my ($last_res) = $$ranges[scalar(@$ranges) - 1]; # BM
    my ($first_res) = $$ranges[0]; # BM
    my $target_size = ($last_res - $first_res) + 1; # BM

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);

    my $white = $image->colorAllocate(255, 255, 255);
    my $black = $image->colorAllocate(0, 0, 0);

    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    my $grey = $image->colorAllocate(204, 204, 204);
    my $blue = $image->colorAllocate(0, 0, 255 );
    my $darkgrey = $image->colorAllocate(100, 100, 100);
    my $purple = $image->colorAllocate(200, 0, 255);
    my $orange = $image->colorAllocate(255, 200, 0);
    my $darkgreen = $image->colorAllocate(100, 200, 100);
    my $whiteblue = $image->colorAllocate(100, 200, 255);
    my $rose = $image->colorAllocate(255,100,80);
    my $darkpurple = $image->colorAllocate(150, 0, 200);
    my $darkyellow = $image->colorAllocate(220, 220, 0);

    my @colors = ($darkyellow, $darkpurple, $rose, $darkgrey, $green, $whiteblue, $purple, $yellow, $orange, $blue);

    #$image->transparent($white);
    $image->interlaced('true');

    #axis
    my $vertical_axis_step = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 10);
    my $horizontal_axis_step = int(($DEFAULT_WIDTH - $LEFT_MARGIN - $RIGHT_MARGIN)/ ($target_size / 10));
    my $coef = int($target_size / 100);


    for(my $i = 0; $i <= 10; $i++) {
        $image->line($LEFT_MARGIN, $TOP_MARGIN + $vertical_axis_step * $i, $DEFAULT_WIDTH - $RIGHT_MARGIN, $TOP_MARGIN + $vertical_axis_step * $i, $grey);
    }
    $image->line($LEFT_MARGIN, $TOP_MARGIN, $LEFT_MARGIN, $DEFAULT_HEIGHT - $BOTTOM_MARGIN, $black);
    $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN, $TOP_MARGIN, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DEFAULT_HEIGHT - $BOTTOM_MARGIN, $grey);
    $image->line($LEFT_MARGIN, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $DEFAULT_WIDTH - $RIGHT_MARGIN, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $black);

=head
    for(my $i = 0; $i < int($target_size / 10) + 1; $i++) {
        $image->line($LEFT_MARGIN + $i * $horizontal_axis_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $LEFT_MARGIN + $i * $horizontal_axis_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 5, (($i == 0) ? $black : $grey));
        if($target_size < 100) {
            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, ($i * 10));
        } else {
            if(($i % $coef) == 0) {
                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, ($i * 10));
            }
        }
    }
=cut
    
    # draw graphics: BM
    my $horizontal_step = $horizontal_axis_step / 10;
    for(my $i = 0; $i < $target_size; $i++) {
	my $label = $$ranges[$i];
        my $label0 = $$ranges[0];
        if (defined($label)  && ($label =~ /^\d+$/) &&($label % 10) == 0 ){
	        $image->line($LEFT_MARGIN + ($label - $label0) * $horizontal_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $LEFT_MARGIN + ($label - $label0) * $horizontal_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 5, (($i == 0) ? $black : $grey));
        if($target_size < 100) {
            $image->stringFT($black, $DEFAULT_AXIS_FONT, $FONT_SIZE, 0, $LEFT_MARGIN + ($label - $label0) * $horizontal_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, $label);
        } else {
            if(defined($label)  && ($label =~ /^\d+$/) && ($label % (10*$coef)) == 0) {
                $image->stringFT($black, $DEFAULT_AXIS_FONT, $FONT_SIZE, 0, $LEFT_MARGIN + ($label - $label0) * $horizontal_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, $label);
            }
        }
	}
    }

#    my $horizontal_step = $horizontal_axis_step / 10;
    my $vertical_step = $vertical_axis_step;
    # draw alignment

    $image->setThickness(1);

    my $index = 0;

    # draw start_model graph    
    my @start_distances = split(/\s+/, trim($start_model->{'distances'}));
    my $previous_x = -1;
    my $previous_y = -1;
    my $current_color = $darkgreen;
    $image->setThickness(2);
    @start_distances = $self->replace(\@start_distances, 5.0);
    @start_distances = $self->smooth(\@start_distances);

            for(my $i = 0; $i < scalar(@start_distances); $i++) {
		if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
		if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($start_distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $start_distances[$i];

                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);

                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
     # end draw start_model graph

    # draw refined_model graph    
    my @refined_distances = split(/\s+/, trim($refined_model->{'distances'}));
    $previous_x = -1;
    $previous_y = -1;
    $current_color = $blue;
    $image->setThickness(2);
    @refined_distances = $self->replace(\@refined_distances, 5.0);
    @refined_distances = $self->smooth(\@refined_distances);

            for(my $i = 0; $i < scalar(@refined_distances); $i++) {
                if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
                if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($refined_distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $refined_distances[$i];

                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);

                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
     # end draw refined_model graph


     # draw differences
     my @diff_distances = ();   
     for(my $i = 0; $i < scalar(@start_distances); $i++) {
	push(@diff_distances, 'X');
     }
    
     for(my $i = 0; $i < scalar(@start_distances); $i++) {
        if(($start_distances[$i] =~ /^[0-9.]+$/) && ($refined_distances[$i] =~ /^[0-9.]+$/)) {
              $diff_distances[$i] =  $refined_distances[$i] - $start_distances[$i] ;
        }
     }

    $previous_x = -1;
    $previous_y = -1;
    $current_color = $red;
    $image->setThickness(2);
    @diff_distances = $self->replace(\@diff_distances, 5.0);
    @diff_distances = $self->smooth(\@diff_distances);

            for(my $i = 0; $i < scalar(@diff_distances); $i++) {
                if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
                if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($diff_distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $diff_distances[$i];

                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);

                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
    # end draw differences

    # draw axises' titles
    $image->setThickness(1);
    $image->filledRectangle(0, 0, $DEFAULT_WIDTH, $TOP_MARGIN - 1, $white);
    $image->filledRectangle(0, $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 1, $DEFAULT_WIDTH, $DEFAULT_HEIGHT, $white);

    my $horizontal_length_step = ($horizontal_axis_step / 10);
=head
    for(my $i = 0; $i < $target_size; $i++) {
        if(in_array(($i + 1), @$ranges)) {
            $image->filledRectangle($LEFT_MARGIN + $i*$horizontal_length_step, ($DEFAULT_HEIGHT - $BOTTOM_MARGIN) + 20, $LEFT_MARGIN + $i*$horizontal_length_step + $horizontal_length_step, ($DEFAULT_HEIGHT - $BOTTOM_MARGIN) + 28, $darkgreen);
        }
    }
=cut

    for(my $i = 0; $i <= 10; $i++) {
        $image->stringFT($black, $DEFAULT_AXIS_FONT, $FONT_SIZE, 0, $LEFT_MARGIN - 22, $TOP_MARGIN + $vertical_axis_step * $i + 5, 5 - $i);
    }
    $image->stringFT($black, $DEFAULT_TOP_FONT, $FONT_SIZE, 0, int($DEFAULT_WIDTH / 2) - 80, 20, $TOP_TITLE);
    $image->stringFT($black, $DEFAULT_TOP_FONT, $FONT_SIZE, 0, int($DEFAULT_WIDTH / 2) - 50, $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 15, $BOTTOM_TITLE);
    $image->stringFT($black, $DEFAULT_TOP_FONT, $FONT_SIZE, (3.14/2), $LEFT_MARGIN - 30, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + 100, $LEFT_TITLE);




   # legend
   my $history_step = 20;
   $image->setThickness(2);
   $current_color = $darkgreen;
               $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*0 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*0 + 5, $current_color);
            $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*0 + 5, 3, 3, 0, 360, $current_color);
            $image->stringFT($black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*0 + 9, 'starting model');

    $current_color = $blue;
               $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*1 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*1 + 5, $current_color);
            $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*1 + 5, 3, 3, 0, 360, $current_color);
            $image->stringFT($black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*1 + 9, $refined_model->{name});  

   $current_color = $red;
        $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*2 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*2 + 5, $red);
        $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*2 + 5, 3, 3, 0, 360, $red);
        $image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*2 + 9, 'Difference');
        $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*2 + 20, '('.$refined_model->{'name'}.' -');
	$image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 42, $TOP_MARGIN + $history_step*2 + 31,  'starting model)');

return $image;

}


sub draw_lacc_distances_plot {
    my ($self, $correct_target_name, $start_model, $refined_model,$ranges) = @_;

    my $TOP_TITLE = 'Target ' . $correct_target_name;
    my $BOTTOM_TITLE = 'Residue';
    my $LEFT_TITLE = 'CA-CA difference, A';

    my $DEFAULT_WIDTH = 800;
    my $DEFAULT_HEIGHT = 300;
    my $LEFT_MARGIN = 50;
    my $RIGHT_MARGIN = 140;
    my $TOP_MARGIN = 30;
    my $BOTTOM_MARGIN = 40;

    #my ($target_size) = $$ranges[scalar(@$ranges) - 1];
    my ($last_res) = $$ranges[scalar(@$ranges) - 1]; # BM
    my ($first_res) = $$ranges[0]; # BM
    my $target_size = ($last_res - $first_res) + 1; # BM

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);

    my $white = $image->colorAllocate(255, 255, 255);
    my $black = $image->colorAllocate(0, 0, 0);

    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    my $grey = $image->colorAllocate(204, 204, 204);
    my $blue = $image->colorAllocate(0, 0, 255 );
    my $darkgrey = $image->colorAllocate(100, 100, 100);
    my $purple = $image->colorAllocate(200, 0, 255);
    my $orange = $image->colorAllocate(255, 200, 0);
    my $darkgreen = $image->colorAllocate(100, 200, 100);
    my $whiteblue = $image->colorAllocate(100, 200, 255);
    my $rose = $image->colorAllocate(255,100,80);
    my $darkpurple = $image->colorAllocate(150, 0, 200);
    my $darkyellow = $image->colorAllocate(220, 220, 0);

    my @colors = ($darkyellow, $darkpurple, $rose, $darkgrey, $green, $whiteblue, $purple, $yellow, $orange, $blue);

    #$image->transparent($white);
    $image->interlaced('true');

    #axis
    my $vertical_axis_step = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 10);
    my $horizontal_axis_step = int(($DEFAULT_WIDTH - $LEFT_MARGIN - $RIGHT_MARGIN)/ ($target_size / 10));
    my $coef = int($target_size / 100);

    for(my $i = 0; $i <= 10; $i++) {
        $image->line($LEFT_MARGIN, $TOP_MARGIN + $vertical_axis_step * $i, $DEFAULT_WIDTH - $RIGHT_MARGIN, $TOP_MARGIN + $vertical_axis_step * $i, $grey);
    }
    $image->line($LEFT_MARGIN, $TOP_MARGIN, $LEFT_MARGIN, $DEFAULT_HEIGHT - $BOTTOM_MARGIN, $black);
    $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN, $TOP_MARGIN, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DEFAULT_HEIGHT - $BOTTOM_MARGIN, $grey);
    $image->line($LEFT_MARGIN, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $DEFAULT_WIDTH - $RIGHT_MARGIN, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $black);

=head
    for(my $i = 0; $i < int($target_size / 10) + 1; $i++) {
        $image->line($LEFT_MARGIN + $i * $horizontal_axis_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $LEFT_MARGIN + $i * $horizontal_axis_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 5, (($i == 0) ? $black : $grey));
        if($target_size < 100) {
            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, ($i * 10));
        } else {
            if(($i % $coef) == 0) {
                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, ($i * 10));
            }
        }
    }
=cut

    my $horizontal_step = $horizontal_axis_step / 10;
    for(my $i = 0; $i < $target_size; $i++) {
        my $label = $$ranges[$i];
        my $label0 = $$ranges[0];
        if (defined($label)  && ($label =~ /^\d+$/) && ($label % 10) == 0 ){
                $image->line($LEFT_MARGIN + ($label - $label0 ) * $horizontal_step , int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $LEFT_MARGIN + ($label - $label0 ) * $horizontal_step , int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 5, (($i == 0) ? $black : $grey));
        if($target_size < 100) {
            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + ($label - $label0 ) * $horizontal_step  - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, $label);
        } else {
            if(defined($label)  && ($label =~ /^\d+$/) && ($label % (10*$coef)) == 0) {
                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + ($label - $label0) * $horizontal_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, $label);
            }
        }
        }
    }

    my $vertical_step = $vertical_axis_step;
    # draw alignment

    $image->setThickness(1);

    my $index = 0;

    # draw start_model graph    
    my @start_distances = split(/\s+/, trim($start_model->{'ALIGNMENT_4'}));
    my $previous_x = -1;
    my $previous_y = -1;
    my $current_color = $darkgreen;
    $image->setThickness(2);

    @start_distances = $self->replace(\@start_distances, 5.0);
    @start_distances = $self->smooth(\@start_distances);
            for(my $i = 0; $i < scalar(@start_distances); $i++) {
		if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
                if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($start_distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $start_distances[$i];

                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);

                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
     # end draw start_model graph

    # draw refined_model graph    
    my @refined_distances = split(/\s+/, trim($refined_model->{'ALIGNMENT_4'}));
    $previous_x = -1;
    $previous_y = -1;
    $current_color = $blue;
    $image->setThickness(2);
    
    @refined_distances = $self->replace(\@refined_distances, 5.0);
    @refined_distances = $self->smooth(\@refined_distances);

            for(my $i = 0; $i < scalar(@refined_distances); $i++) {
                if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
                if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($refined_distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $refined_distances[$i];

                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);

                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
     # end draw refined_model graph

     # draw differences
     my @diff_distances = ();
     for(my $i = 0; $i < scalar(@start_distances); $i++) {
        push(@diff_distances, 'X');
     }

     for(my $i = 0; $i < scalar(@start_distances); $i++) {
        if(($start_distances[$i] =~ /^[0-9.]+$/) && ($refined_distances[$i] =~ /^[0-9.]+$/)) {
              $diff_distances[$i] =  $refined_distances[$i] - $start_distances[$i] ;
        }
     }
    @diff_distances = $self->replace(\@diff_distances, 5.0);
    @diff_distances = $self->smooth(\@diff_distances);
    $previous_x = -1;
    $previous_y = -1;
    $current_color = $red;
    $image->setThickness(2);


            for(my $i = 0; $i < scalar(@diff_distances); $i++) {
		if ((defined $first_res) && (defined $last_res)){ if ($i < $first_res - 1 || $i > $last_res - 1 ){next;} }
                if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($diff_distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $diff_distances[$i];

                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);

                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
    # end draw differences

    # draw axises' titles
    $image->setThickness(1);
    $image->filledRectangle(0, 0, $DEFAULT_WIDTH, $TOP_MARGIN - 1, $white);
    $image->filledRectangle(0, $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 1, $DEFAULT_WIDTH, $DEFAULT_HEIGHT, $white);

    my $horizontal_length_step = ($horizontal_axis_step / 10);
=head
    for(my $i = 0; $i < $target_size; $i++) {
        if(in_array(($i + 1), @$ranges)) {
            $image->filledRectangle($LEFT_MARGIN + $i*$horizontal_length_step, ($DEFAULT_HEIGHT - $BOTTOM_MARGIN) + 20, $LEFT_MARGIN + $i*$horizontal_length_step + $horizontal_length_step, ($DEFAULT_HEIGHT - $BOTTOM_MARGIN) + 28, $darkgreen);
        }
    }
=cut

    for(my $i = 0; $i <= 10; $i++) {
        $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN - 22, $TOP_MARGIN + $vertical_axis_step * $i + 5, 5 - $i);
    }
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, int($DEFAULT_WIDTH / 2) - 80, 20, $TOP_TITLE);
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, int($DEFAULT_WIDTH / 2) - 50, $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 15, $BOTTOM_TITLE);
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, (3.14/2), $LEFT_MARGIN - 30, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + 100, $LEFT_TITLE);


   # legend
   my $history_step = 20;
   $image->setThickness(2);
   $current_color = $darkgreen;
               $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*0 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*0 + 5, $current_color);
            $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*0 + 5, 3, 3, 0, 360, $current_color);
            $image->stringFT($black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*0 + 9, $start_model->{'MODEL_NAME'});

    $current_color = $blue;
               $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*1 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*1 + 5, $current_color);
            $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*1 + 5, 3, 3, 0, 360, $current_color);
            $image->stringFT($black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*1 + 9, $refined_model->{MODEL_NAME});

   $current_color = $red;
        $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*2 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*2 + 5, $red);
        $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*2 + 5, 3, 3, 0, 360, $red);
        $image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*2 + 9, 'Difference');
        $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*2 + 20, '('.$refined_model->{'MODEL_NAME'}.' -');
        $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 42, $TOP_MARGIN + $history_step*2 + 31,  $start_model->{'MODEL_NAME'}.')');

return $image;

}




######################################### TRERE ARE GOING TO BE OLD FUNCTIONALITY OF TEMPLATES


sub draw_templatesvstargets {
    my ($self, $correct_target_name, $view_templates, $view_models, $view_differences,
        $ranges, $templates, $models, $selected_templates, $selected_models, $main_template_id) = @_;
    
    my $TOP_TITLE = 'Target ' . $correct_target_name;
    my $BOTTOM_TITLE = 'Residue';
    my $LEFT_TITLE = 'CA-CA difference, A';
    
    my $DEFAULT_WIDTH = 800;
    my $DEFAULT_HEIGHT = 300;
    my $LEFT_MARGIN = 50;
    my $RIGHT_MARGIN = 140;
    my $TOP_MARGIN = 30;
    my $BOTTOM_MARGIN = 40;

    #my ($target_size) = $$ranges[scalar(@$ranges) - 1];   
    #my ($last_res) = $$ranges[scalar(@$ranges) - 1]; # BM
    #my ($first_res) = $$ranges[0]; # BM
    my ($last_res) = defined($$ranges[scalar(@$ranges) - 1]) ? $$ranges[scalar(@$ranges) - 1] :0; # BM
    my ($first_res) = defined($$ranges[0]) ? $$ranges[0] :0 ; # BM

    my $target_size = ($last_res - $first_res) + 1; # BM
        
    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);
    
    my $white = $image->colorAllocate(255, 255, 255);
    my $black = $image->colorAllocate(0, 0, 0);
    
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);
    my $grey = $image->colorAllocate(204, 204, 204);
    my $blue = $image->colorAllocate(0, 0, 255 );
    my $darkgrey = $image->colorAllocate(100, 100, 100);
    my $purple = $image->colorAllocate(200, 0, 255);
    my $orange = $image->colorAllocate(255, 200, 0);
    my $darkgreen = $image->colorAllocate(100, 200, 100);
    my $whiteblue = $image->colorAllocate(100, 200, 255);
    my $rose = $image->colorAllocate(255,100,80);
    my $darkpurple = $image->colorAllocate(150, 0, 200);
    my $darkyellow = $image->colorAllocate(220, 220, 0);
    
    my @colors = ($darkyellow, $darkpurple, $rose, $darkgrey, $green, $whiteblue, $purple, $yellow, $orange, $blue);
    
    #$image->transparent($white);
    $image->interlaced('true');

    #axis
    my $vertical_axis_step = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 10);
    my $horizontal_axis_step = int(($DEFAULT_WIDTH - $LEFT_MARGIN - $RIGHT_MARGIN)/ ($target_size / 10));
    my $coef = int($target_size / 100);
    
    for(my $i = 0; $i <= 10; $i++) {
        $image->line($LEFT_MARGIN, $TOP_MARGIN + $vertical_axis_step * $i, $DEFAULT_WIDTH - $RIGHT_MARGIN, $TOP_MARGIN + $vertical_axis_step * $i, $grey);
    }
    $image->line($LEFT_MARGIN, $TOP_MARGIN, $LEFT_MARGIN, $DEFAULT_HEIGHT - $BOTTOM_MARGIN, $black);
    $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN, $TOP_MARGIN, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DEFAULT_HEIGHT - $BOTTOM_MARGIN, $grey);
    $image->line($LEFT_MARGIN, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $DEFAULT_WIDTH - $RIGHT_MARGIN, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $black);
    
#    for(my $i = 0; $i < int($target_size / 10) + 1; $i++) {
#        $image->line($LEFT_MARGIN + $i * $horizontal_axis_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $LEFT_MARGIN + $i * $horizontal_axis_step, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 5, (($i == 0) ? $black : $grey));
#        if($target_size < 100) {
#            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, ($i * 10));
#        } else {
#            if(($i % $coef) == 0) {
#                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, ($i * 10));
#            }
#        }
#    }

    # draw graphics: BM
    my $horizontal_step = $horizontal_axis_step / 10;
    for(my $i = 0; $i < $target_size; $i++) {
	my $label = $$ranges[$i];
	my $label0 = $$ranges[0];
	if ((defined($label) && ($label =~ /^\d+$/)) && (($label % 10) == 0 )){ #(($label % 10) == 0 ){
        	$image->line($LEFT_MARGIN + ($label - $label0 ) * $horizontal_step , int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN, $LEFT_MARGIN + ($label - $label0 ) * $horizontal_step , int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 5, (($i == 0) ? $black : $grey));
        if($target_size < 100) {
            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + ($label - $label0 ) * $horizontal_step  - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, $label);
        } else {
            if(defined($label)  && ($label =~ /^\d+$/) && ($label % (10*$coef)) == 0) {
                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + ($label - $label0) * $horizontal_step - 10, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN + 18, $label);
            }
        }
	}
    }

    
    #my $horizontal_step = $horizontal_axis_step / 10;
    my $vertical_step = $vertical_axis_step;
    # draw alignment
    
    $image->setThickness(1);

    my $index = 0;
    if($view_templates) {
        foreach my $template_key (@$selected_templates) {
            my @distances = split(/\s+/, trim($$templates[$template_key]{'distances'}));
	    @distances = $self->replace(\@distances, 5.0);
            @distances = $self->smooth(\@distances);
            my $previous_x = -1;
            my $previous_y = -1;
            
            my $current_color = $colors[$index];
            
            if($template_key eq $main_template_id) {
                $current_color = $darkgreen;
                $image->setThickness(2);
            }
            
            for(my $i = 0; $i < scalar(@distances); $i++) {
		if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
                if(! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $distances[$i];
                    
                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $current_color);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $current_color);
                    
                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }

            if($template_key eq $main_template_id) {
                $image->setThickness(1);
            }
            
            $index++;
        }
    }
    
    $image->setThickness(2);
    $index = 0;
    if($view_models) {
        foreach my $model_key (@$selected_models) {
            my @distances = split(/\s+/, trim($$models[$model_key]{'distances'}));
	    @distances = $self->replace(\@distances, 5.0);
	    @distances = $self->smooth(\@distances);
            my $previous_x = -1;
            my $previous_y = -1;
            
            for(my $i = 0; $i < scalar(@distances); $i++) {
		if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
		if (! in_array(($i + 1), @$ranges)){
			$previous_x = -1;
			$previous_y = -1;
			next;
		}
                if($distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $distances[$i];
                    
                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $blue);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $blue); #$colors[9 - $index]
                    
                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
            
            $index++;
        }
    }
    
    $index = 0;
    if($view_differences) {
        foreach my $model_key (@$selected_models) {
            my @models_distances = split(/\s+/, trim($$models[$model_key]{'distances'}));
	    @models_distances = $self->replace(\@models_distances, 5.0);
            my @distances = ();
            for(my $i = 0; $i < scalar(@models_distances); $i++) {
                push(@distances, 'X');
            }
            my $previous_x = -1;
            my $previous_y = -1;
            
            my @templates_distances = split(/\s+/, trim($$templates[$main_template_id]{'distances'}));
	    @templates_distances = $self->replace(\@templates_distances, 5.0);
            
            for(my $i = 0; $i < scalar(@templates_distances); $i++) {
                if(($models_distances[$i] =~ /^[0-9.]+$/) && ($templates_distances[$i] =~ /^[0-9.]+$/)) {
                    $distances[$i] = $models_distances[$i] - $templates_distances[$i];
                }
            }
            @distances = $self->smooth(\@distances);
            for(my $i = 0; $i < scalar(@distances); $i++) {
		if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
		if (! in_array(($i + 1), @$ranges)){
                        $previous_x = -1;
                        $previous_y = -1;
                        next;
                }

                if($distances[$i] ne 'X') {
                    my $current_x = $horizontal_step*($i - $first_res + 1) + $LEFT_MARGIN;
                    my $current_y = int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + $TOP_MARGIN - $vertical_step * $distances[$i];
                    
                    if($previous_x >= 0) {
                        $image->line($current_x, $current_y, $previous_x, $previous_y, $red);
                    }
                    $image->filledArc($current_x, $current_y, 3, 3, 0, 360, $red); #
                    
                    $previous_x = $current_x;
                    $previous_y = $current_y;
                } else {
                    $previous_x = -1;
                    $previous_y = -1;
                }
            }
            
            $index++;
        }
    }
    
    $image->setThickness(1);
    $image->filledRectangle(0, 0, $DEFAULT_WIDTH, $TOP_MARGIN - 1, $white);
    $image->filledRectangle(0, $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 1, $DEFAULT_WIDTH, $DEFAULT_HEIGHT, $white);

    my $horizontal_length_step = ($horizontal_axis_step / 10);

    for(my $i = 0; $i < $target_size; $i++) {
        if(in_array(($i + 1), @$ranges)) {
#            $image->filledRectangle($LEFT_MARGIN + $i*$horizontal_length_step, ($DEFAULT_HEIGHT - $BOTTOM_MARGIN) + 20, $LEFT_MARGIN + $i*$horizontal_length_step + $horizontal_length_step, ($DEFAULT_HEIGHT - $BOTTOM_MARGIN) + 28, $darkgreen);
        }
    }

    for(my $i = 0; $i <= 10; $i++) {
        $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN - 22, $TOP_MARGIN + $vertical_axis_step * $i + 5, 5 - $i);
    }
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, int($DEFAULT_WIDTH / 2) - 80, 20, $TOP_TITLE);
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, int($DEFAULT_WIDTH / 2) - 50, $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 15, $BOTTOM_TITLE);
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, (3.14/2), $LEFT_MARGIN - 30, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + 100, $LEFT_TITLE);

    # legend
    my $history_step = 20;
    
    my $index_2 = 0;
    if($view_templates) {
        for(my $i = 0; $i < scalar(@$selected_templates); $i++) {
            my $current_color = $colors[$i];
            if($$selected_templates[$i] == $main_template_id) {
                $image->setThickness(2);
                $current_color = $darkgreen;
            } else {
                $image->setThickness(1);
            }
            
            $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*$i + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*$i + 5, $current_color);
            $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*$i + 5, 3, 3, 0, 360, $current_color);
            $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*$i + 9, $$templates[$$selected_templates[$i]]{'name'});
            $index_2 = $i;
        }
        $index_2++;
    }
    
    my $index_3 = 0;
    if($view_models) {
        $image->setThickness(2);
        for(my $i = 0; $i < scalar(@$selected_models); $i++) {
            $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*($i + $index_2) + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*($i + $index_2) + 5, $colors[9 - $i]);
            $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*($i + $index_2) + 5, 3, 3, 0, 360, $colors[9 - $i]);
            $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*($i + $index_2) + 9, $$models[$$selected_models[$i]]{'name'});
            $index_3 = $i;
        }
        $index_3++;
    }
    
    if($view_differences) {
        $index_3 += $index_2;
        $image->setThickness(2);
        $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*$index_3 + 5, $DEFAULT_WIDTH - $RIGHT_MARGIN + 30, $TOP_MARGIN + $history_step*$index_3 + 5, $red);
        $image->filledArc($DEFAULT_WIDTH - $RIGHT_MARGIN + 20, $TOP_MARGIN + $history_step*$index_3 + 5, 3, 3, 0, 360, $red);
        $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 37, $TOP_MARGIN + $history_step*$index_3 + 9, 'Difference');
#        $image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*$index_3 + 20, '(' . $$models[$$selected_models[0]]{'name'} . ' - ' . $$templates[$main_template_id]{'name'} . ')');
	$image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 10, $TOP_MARGIN + $history_step*$index_3 + 20, '(' . $$models[$$selected_models[0]]{'name'});
	$image->stringFT($black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - $RIGHT_MARGIN + 42, $TOP_MARGIN + $history_step*$index_3 + 31,  ' - ' . $$templates[$main_template_id]{'name'}.' )');
    }
    
    return $image;
}



sub replace{
    my ($self, $refArr, $cutOff) = @_;
    my @arr = @{$refArr};
    my @result = ();
    for(my $i = 0 ; $i < scalar(@arr); $i++){
	if ($arr[$i] eq 'X' || $arr[$i] > $cutOff){
		$result[$i] = $cutOff;
	} else {
		$result[$i] = $arr[$i];
	}
    }
    return @result;
}


sub smooth{
    my ($self, $refArr) = @_;
    my @arr = @{$refArr};
    my @result = ();
    for(my $i = 0 ; $i < scalar(@arr); $i++){
	if ($i == 0){
		push @result, 0.5*($arr[$i] + $arr[$i + 1]);
	} elsif ($i == scalar(@arr) - 1){
                push @result, 0.5*($arr[$i] + $arr[$i - 1]);
	} else {
		push @result, ($arr[$i - 1] + $arr[$i] + $arr[$i + 1])/3;
	}
    }	
    return @result;
}



sub draw_templatesvsmodels_bars {
    my ($self, $TOP_TITLE, $view_templates, $view_models, $view_differences, $ranges, $template_data, $model_data) = @_;

    my @template_range = split(/\s+/, trim($$template_data{distances}));
    my @model_range = split(/\s+/, trim($$model_data{distances}));

    my $DEFAULT_WIDTH = 800;
    my $DEFAULT_HEIGHT = 60;
    my $LEFT_MARGIN = 50;
    my $RIGHT_MARGIN = 140;
    
    my $BAR_HEIGHT = 8;

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);

    my $color_white     = $image->colorAllocate(255, 255, 255);
    my $color_black     = $image->colorAllocate(0, 0, 0);
    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 209, 0); #ffd100
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000
    my $color_grey      = $image->colorAllocate(204, 204, 204);

    #my ($target_size) = $$ranges[scalar(@$ranges) - 1];
    my ($last_res) = $$ranges[scalar(@$ranges) - 1]; # BM
    my ($first_res) = $$ranges[0]; # BM
    my $target_size = ($last_res - $first_res) + 1; # BM
    
    my $horizontal_axis_step = int(($DEFAULT_WIDTH - $LEFT_MARGIN - $RIGHT_MARGIN)/ ($target_size / 10));
    my $horizontal_step = $horizontal_axis_step / 10;
    
    my $TOP_MARGIN = 10;
    my $BETWEEN_BARS_DISTANCE = 5;

    my $coef = int($target_size / 100);
    
#    for(my $i = 0; $i <= int($target_size / 10); $i++) {
#        $image->line($LEFT_MARGIN + $i * $horizontal_axis_step, $TOP_MARGIN - 2, $LEFT_MARGIN + $i * $horizontal_axis_step, $TOP_MARGIN + 1, $color_grey);
#        if(($target_size < 100) || (($i % $coef) == 0)) {
#            $image->stringFT($color_black, $DEFAULT_AXIS_FONT, 6, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 4, $TOP_MARGIN - 3, ($i * 10));
#        }
#    }

    for(my $i = 0; $i < $target_size ; $i++) {
	my $label = $$ranges[$i];
	my $label0 = $$ranges[0];
	if ((defined($label) && ($label =~ /^\d+$/)) && (($label % 10) == 0 )){ #(($label % 10) == 0 )(($label % 10) == 0){
        $image->line($LEFT_MARGIN + ($label - $label0) * $horizontal_step, $TOP_MARGIN - 2, $LEFT_MARGIN + ($label - $label0) * $horizontal_step, $TOP_MARGIN + 1, $color_grey);
        if(($target_size < 100) || (($label % (10*$coef)) == 0)) {
            $image->stringFT($color_black, $DEFAULT_AXIS_FONT, 6, 0, $LEFT_MARGIN + ($label - $label0) * $horizontal_step - 4, $TOP_MARGIN - 3, $label);
        }
	}
    }


    $TOP_MARGIN += 3;
	
    if($view_templates) {
	@template_range = $self->replace(\@template_range, 5.0);
        for(my $i = 0; $i < scalar(@template_range); $i++) {
	    if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
	    my $current_color = $color_white;
	    if (in_array(($i + 1), @$ranges)){

            if(!($template_range[$i] =~ /^([\-\.0-9]+)$/)) {
                $current_color = $color_white;
            } elsif($template_range[$i] <= -5) {
                $current_color = $color_darkblue;
            } elsif(($template_range[$i] > -5) && ($template_range[$i] <= -2)) {
                $current_color = $color_sky;
            } elsif(($template_range[$i] > -2) && ($template_range[$i] <= -0.5)) {
                $current_color = $color_green;
            } elsif(($template_range[$i] > -0.5) && ($template_range[$i] <= 0.5)) {
                $current_color = $color_yellow;
            } elsif(($template_range[$i] > 0.5) && ($template_range[$i] <= 2)) {
                $current_color = $color_orange;
            } elsif(($template_range[$i] > 2) && ($template_range[$i] < 5)) {
                $current_color = $color_red;
            } elsif($template_range[$i] >= 5) {
                $current_color = $color_darkred;
            }
            }
            $image->filledRectangle($LEFT_MARGIN + ($i - $first_res + 1)*$horizontal_step, $TOP_MARGIN, $LEFT_MARGIN + $horizontal_step * ($i - $first_res + 2), $TOP_MARGIN + $BAR_HEIGHT, $current_color);
        }
        $image->stringFT($color_black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - 120, $TOP_MARGIN + 7, $$template_data{'name'});
        $TOP_MARGIN += $BAR_HEIGHT + $BETWEEN_BARS_DISTANCE;
    }

    if($view_models) {
	@model_range =  $self->replace(\@model_range,5.0);
        for(my $i = 0; $i < scalar(@model_range); $i++) {
	    if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
            my $current_color = $color_white;
	    if (in_array(($i + 1), @$ranges)){
            if(!($model_range[$i] =~ /^([\-\.0-9]+)$/)) {
                $current_color = $color_white;
            } elsif($model_range[$i] <= -5) {
                $current_color = $color_darkblue;
            } elsif(($model_range[$i] > -5) && ($model_range[$i] <= -2)) {
                $current_color = $color_sky;
            } elsif(($model_range[$i] > -2) && ($model_range[$i] <= -0.5)) {
                $current_color = $color_green;
            } elsif(($model_range[$i] > -0.5) && ($model_range[$i] <= 0.5)) {
                $current_color = $color_yellow;
            } elsif(($model_range[$i] > 0.5) && ($model_range[$i] <= 2)) {
                $current_color = $color_orange;
            } elsif(($model_range[$i] > 2) && ($model_range[$i] < 5)) {
                $current_color = $color_red;
            } elsif($model_range[$i] >= 5) {
                $current_color = $color_darkred;
            }
            }
            $image->filledRectangle($LEFT_MARGIN + ($i - $first_res + 1)*$horizontal_step, $TOP_MARGIN, $LEFT_MARGIN + $horizontal_step * ($i - $first_res + 2), $TOP_MARGIN + $BAR_HEIGHT, $current_color);
        }
        $image->stringFT($color_black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - 120, $TOP_MARGIN + 7, $$model_data{'name'});
        $TOP_MARGIN += $BAR_HEIGHT + $BETWEEN_BARS_DISTANCE;
    }

    if($view_differences) {
        my @distances = ();
        for(my $i = 0; $i < scalar(@model_range); $i++) {
            push(@distances, 'X');
        }
        my $previous_x = -1;
        my $previous_y = -1;
        
        for(my $i = 0; $i < scalar(@template_range); $i++) {
	    @template_range = $self->replace(\@template_range, 5.0);
	    @model_range =  $self->replace(\@model_range,5.0);
            if(($model_range[$i] =~ /^[0-9.]+$/) && ($template_range[$i] =~ /^[0-9.]+$/)) {
                $distances[$i] = $model_range[$i] - $template_range[$i];
            }
        }
        
        for(my $i = 0; $i < scalar(@distances); $i++) {
	    if ($i < $first_res - 1 || $i > $last_res - 1 ){next;}
            my $current_color = $color_white;
            if (in_array(($i + 1), @$ranges)){
	    if(!($distances[$i] =~ /^([\-\.0-9]+)$/)) {
                $current_color = $color_white;
            } elsif($distances[$i] <= -5) {
                $current_color = $color_darkblue;
            } elsif(($distances[$i] > -5) && ($distances[$i] <= -2)) {
                $current_color = $color_sky;
            } elsif(($distances[$i] > -2) && ($distances[$i] <= -0.5)) {
                $current_color = $color_green;
            } elsif(($distances[$i] > -0.5) && ($distances[$i] <= 0.5)) {
                $current_color = $color_yellow;
            } elsif(($distances[$i] > 0.5) && ($distances[$i] <= 2)) {
                $current_color = $color_orange;
            } elsif(($distances[$i] > 2) && ($distances[$i] < 5)) {
                $current_color = $color_red;
            } elsif($distances[$i] >= 5) {
                $current_color = $color_darkred;
            }
            }
            $image->filledRectangle($LEFT_MARGIN + ($i - $first_res + 1)*$horizontal_step, $TOP_MARGIN, $LEFT_MARGIN + $horizontal_step * ($i - $first_res + 2), $TOP_MARGIN + $BAR_HEIGHT, $current_color);
        }
        $image->stringFT($color_black, $DEFAULT_TOP_FONT, 9, 0, $DEFAULT_WIDTH - 120, $TOP_MARGIN + 7, 'Difference');
#        $image->stringFT($color_black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - 120, $TOP_MARGIN + 20, '(' . $$model_data{'name'} . ' - ' .  $$template_data{'name'}. ')');
	$image->stringFT($color_black, $DEFAULT_TOP_FONT, 8, 0, $DEFAULT_WIDTH - 120, $TOP_MARGIN + 20, '(model - template)');
    }
    
    return $image;
}


sub draw_templates_coverage_bar {
    my ($self, $ranges, $templates, $models) = @_;
    
    my $DEFAULT_WIDTH = 550;
    my $DEFAULT_HEIGHT = 230;
    my $LEFT_MARGIN = 50;
    my $RIGHT_MARGIN = 5;
    my $TOP_MARGIN = 10;
    my $BOTTOM_MARGIN = 230;

    #my ($target_size) = $$ranges[scalar(@$ranges) - 1];
    my $last_res = $$ranges[scalar(@$ranges) - 1]; # BM
    my $first_res = $$ranges[0]; # BM
    my $target_size = ($last_res - $first_res) + 1; # BM

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);
    
    my $white = $image->colorAllocate(255, 255, 255);
    my $black = $image->colorAllocate(0, 0, 0);
    my $grey = $image->colorAllocate(204, 204, 204);
    my $darkgreen = $image->colorAllocate(100, 200, 100);
    
    #$image->transparent($white);
    $image->interlaced('true');

    my $diagram_templates_count = scalar(@$templates);

    #axis
    my $horizontal_axis_step = int(($DEFAULT_WIDTH - $LEFT_MARGIN - $RIGHT_MARGIN)/ ($target_size / 10));
    my $coef = int($target_size / 100);
    
    my $horizontal_step = $horizontal_axis_step / 10;
    
    $image->setThickness(1);

    # diagram
    my $DIAGRAM_TOP_Y = $DEFAULT_HEIGHT - $BOTTOM_MARGIN + 20;
    my $DIAGRAM_BOTTOM_Y = $DEFAULT_HEIGHT - 20;
    

    my $diagram_vertical_axis_step = (($diagram_templates_count > 0) ? (int($DIAGRAM_BOTTOM_Y - $DIAGRAM_TOP_Y) / $diagram_templates_count) : 0);

    for(my $i = 0; $i <= $diagram_templates_count; $i++) {
        $image->line($LEFT_MARGIN, $DIAGRAM_TOP_Y + $diagram_vertical_axis_step * $i, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DIAGRAM_TOP_Y + $diagram_vertical_axis_step * $i, $grey);
	if ((($diagram_templates_count - $i) % 5) == 0){
             $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN - 18, $DIAGRAM_TOP_Y + $diagram_vertical_axis_step * $i + 5, ($diagram_templates_count - $i));
	}
    }

    $image->line($LEFT_MARGIN, $DIAGRAM_TOP_Y, $LEFT_MARGIN, $DIAGRAM_BOTTOM_Y, $black);
    $image->line($LEFT_MARGIN, $DIAGRAM_BOTTOM_Y, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DIAGRAM_BOTTOM_Y, $black);
    $image->line($LEFT_MARGIN, $DIAGRAM_TOP_Y, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DIAGRAM_TOP_Y, $grey);
    $image->line($DEFAULT_WIDTH - $RIGHT_MARGIN, $DIAGRAM_TOP_Y, $DEFAULT_WIDTH - $RIGHT_MARGIN, $DIAGRAM_BOTTOM_Y, $grey);

#    for(my $i = 0; $i <= int($target_size / 10); $i++) {
#        $image->line($LEFT_MARGIN + $i * $horizontal_axis_step, $DIAGRAM_BOTTOM_Y, $LEFT_MARGIN + $i * $horizontal_axis_step, $DIAGRAM_BOTTOM_Y + 5, (($i == 0) ? $white : $grey));
#        if($target_size < 100) {
#            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, $DIAGRAM_BOTTOM_Y + 18, ($i * 10));
#        } else {
#            if(($i % $coef) == 0) {
#                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + $i * $horizontal_axis_step - 10, $DIAGRAM_BOTTOM_Y + 18, ($i * 10));
#            }
#        }
#    }

    for(my $i = 0; $i < $target_size; $i++) {
	my $label = $$ranges[$i];
	my $label0 = $$ranges[0];
	if (defined($label)  && ($label =~ /^\d+$/) && ($label % 10) == 0){
        	$image->line($LEFT_MARGIN + ($label - $label0 + 1) * $horizontal_step, $DIAGRAM_BOTTOM_Y, $LEFT_MARGIN + ($label - $label0 + 1) * $horizontal_step, $DIAGRAM_BOTTOM_Y + 5, (($i == 0) ? $white : $grey));
        if($target_size < 100) {
            $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + ($label - $label0 + 1) * $horizontal_step - 10, $DIAGRAM_BOTTOM_Y + 18, $label);
        } else {
            if(defined($label)  && ($label =~ /^\d+$/) && ($label % (10*$coef)) == 0) {
                $image->stringFT($black, $DEFAULT_AXIS_FONT, 10, 0, $LEFT_MARGIN + ($label - $label0 + 1) * $horizontal_step - 10, $DIAGRAM_BOTTOM_Y + 18, $label);
            }
        }
	}
    }

    my @residues_counter = ();
    for(my $i = 0; $i < $last_res; $i++) {
        push(@residues_counter, 0);
    }
    
    for(my $i = 0; $i < ($diagram_templates_count); $i++) {
        my @lga_distances = split(/\s+/, trim($$templates[$i]{'distances'}));
        
        for(my $j = 0; $j < scalar(@lga_distances); $j++) {
            if(trim($lga_distances[$j]) ne 'X') {
                $residues_counter[$j]++;
            }
        }
    }

    for(my $i = 0; $i < $last_res; $i++) {
	if ($i+1 < $first_res || $i+1 > $last_res){next;}
	if (!in_array($i+1, @$ranges)){next;}
        $image->filledRectangle($LEFT_MARGIN + $horizontal_step*($i-$first_res + 1), $DIAGRAM_BOTTOM_Y - $diagram_vertical_axis_step*$residues_counter[$i], $LEFT_MARGIN + $horizontal_step*($i - $first_res + 2) - 1, $DIAGRAM_BOTTOM_Y, $darkgreen);
        if($horizontal_step > 2) {
            $image->rectangle($LEFT_MARGIN + $horizontal_step*($i - $first_res + 1), $DIAGRAM_BOTTOM_Y - $diagram_vertical_axis_step*$residues_counter[$i], $LEFT_MARGIN + $horizontal_step*($i - $first_res + 2), $DIAGRAM_BOTTOM_Y, $black);
        }
    }

    #$image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, int($DEFAULT_WIDTH / 2) - 150, 20, $TOP_TITLE);
    #$image->stringFT($black, $DEFAULT_TOP_FONT, 10, 0, int($DEFAULT_WIDTH / 2) - 50, $DEFAULT_HEIGHT - 5, $BOTTOM_TITLE);
    #$image->stringFT($black, $DEFAULT_TOP_FONT, 10, (3.14/2), $LEFT_MARGIN - 30, int(($DEFAULT_HEIGHT - $TOP_MARGIN - $BOTTOM_MARGIN) / 2) + 100, $LEFT_TITLE);

    # Bottom graph titles
    $image->stringFT($black, $DEFAULT_TOP_FONT, 10, (3.14/2), 20, $DEFAULT_HEIGHT - 45, "Number of templates");
    
    return $image;
}



sub draw_alignment_bar {
    my ($self, $ranges) = @_;
	
    my $DEFAULT_WIDTH = 500;
    my $DEFAULT_HEIGHT = 8;
    my $DEFAULT_LEFT_MARGIN = 0;

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);
	
    my $color_white = $image->colorAllocate(255, 255, 255);
    my $color_grey  = $image->colorAllocate(204, 204, 204);
    my $color_black  = $image->colorAllocate(0, 0, 0);
    #$image->transparent($color_white);
    $image->interlaced('true');
    
    my ($target_size) = $$ranges[scalar(@$ranges) - 1];
    my $coef = int($target_size / 100);    
    my $step = $DEFAULT_WIDTH / $target_size;
    for(my $i = 0; $i <= $target_size; $i++) {
        if(($i % 10) == 0) {
            $image->line($DEFAULT_LEFT_MARGIN + int($i * $step), $DEFAULT_HEIGHT - 3, $DEFAULT_LEFT_MARGIN + int($i * $step), $DEFAULT_HEIGHT, $color_grey);
            if(($target_size < 100) || ($i % (10 * $coef)) == 0) {
                $image->stringFT($color_black, $DEFAULT_AXIS_FONT, 6, 0, $DEFAULT_LEFT_MARGIN + int($i * $step) - 4 + 3, 5, $i);
            }
        }
    }
    
    return $image;
}

sub draw_scale_alignment_bar {
    my ($self, $start, $end) = @_;

    my $DEFAULT_WIDTH = 500;
    my $DEFAULT_HEIGHT = 8;
    my $DEFAULT_LEFT_MARGIN = 0;

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);

    my $color_white = $image->colorAllocate(255, 255, 255);
    my $color_grey  = $image->colorAllocate(204, 204, 204);
    my $color_black  = $image->colorAllocate(0, 0, 0);
    #$image->transparent($color_white);
    $image->interlaced('true');

    my $target_size = $end - $start + 1;
    my $coef = int($target_size / 100);
    my $step = $DEFAULT_WIDTH / $target_size;
    my $shift = $start % 10 ;
    for(my $i = 0; $i <= $target_size; $i++) {
        if((($i + $shift) % 10) == 0) {
            $image->line($DEFAULT_LEFT_MARGIN + int($i * $step), $DEFAULT_HEIGHT - 3, $DEFAULT_LEFT_MARGIN + int($i * $step), $DEFAULT_HEIGHT, $color_grey);
            if(($target_size < 100) || (($i + $shift) % (10 * $coef)) == 0) {
                $image->stringFT($color_black, $DEFAULT_AXIS_FONT, 6, 0, $DEFAULT_LEFT_MARGIN + int($i * $step) - 4 + 3, 5, ($start + $i));
            }
        }
    }

    return $image;
}

# draw scale bar of width dependent on target_size
# step are piece-wise function
sub draw_scale_alignment_bar_varwidth {
    my ($self, $start, $end) = @_;
    $start=defined($start)? $start : 0;
    $end=defined($end)? $end : 0;
    my $target_size = $end - $start + 1;
    my $step = 1;
    if ($target_size <= 100){
	$step = 5;
    } elsif ($target_size <= 200){
	$step = 4;
    } elsif ($target_size <= 250){
	$step = 3;
    } elsif ($target_size <= 400){
	$step = 2;
    } else {
	$step = 1;
    }
    my $DEFAULT_WIDTH = $step * $target_size;
    my $DEFAULT_HEIGHT = 8;
    my $DEFAULT_LEFT_MARGIN = 0;

    my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);

    my $color_white = $image->colorAllocate(255, 255, 255);
    my $color_grey  = $image->colorAllocate(204, 204, 204);
    my $color_black  = $image->colorAllocate(0, 0, 0);
    #$image->transparent($color_white);
    $image->interlaced('true');

    my $coef = int($target_size / 100);
    my $shift = $start % 10 ;
    for(my $i = 0; $i <= $target_size; $i++) {
        if((($i + $shift) % 10) == 0) {
            $image->line($DEFAULT_LEFT_MARGIN + int($i * $step), $DEFAULT_HEIGHT - 3, $DEFAULT_LEFT_MARGIN + int($i * $step), $DEFAULT_HEIGHT, $color_grey);
            if(($target_size < 100) || (($i + $shift) % (10 * $coef)) == 0) {
                $image->stringFT($color_black, $DEFAULT_AXIS_FONT, 6, 0, $DEFAULT_LEFT_MARGIN + int($i * $step) - 4 + 3, 5, ($start + $i));
            }
        }
    }

    return $image;
}


sub draw_template_bar {
	my ($self, $data, $ranges) = @_;
	
	my @gamma = ();
	
	my $TOP_LIMIT = 5;
	my $BOTTOM_LIMIT = 0;
	
	my $MAX_HUE = 126;
	
	for(my $i = 0; $i < $MAX_HUE; $i++) {
		my ($r, $g, $b) = $self->HSVtoRGB($i, 1, 255);
		
		push(@gamma, {'red' => $r, 'green' => $g,'blue' => $b});
	}
	
	return $self->draw_bar($data, $ranges, \@gamma, $TOP_LIMIT, $BOTTOM_LIMIT);
}


sub draw_template_scale_bar {
        my ($self, $data, $ranges) = @_;

        my @gamma = ();

        my $TOP_LIMIT = 5;
        my $BOTTOM_LIMIT = 0;

        my $MAX_HUE = 126;

        for(my $i = 0; $i < $MAX_HUE; $i++) {
                my ($r, $g, $b) = $self->HSVtoRGB($i, 1, 255);

                push(@gamma, {'red' => $r, 'green' => $g,'blue' => $b});
        }

        return $self->draw_scale_bar($data, $ranges, \@gamma, $TOP_LIMIT, $BOTTOM_LIMIT);
}

sub draw_model_bar {
	my ($self, $data, $ranges) = @_;        
	my @gamma = ();
	
	my $TOP_LIMIT = 5;
	my $BOTTOM_LIMIT = -5;
	
	my $MAX_HUE = 256;
	
	for(my $i = 0; $i < $MAX_HUE; $i++) {
		my ($r, $g, $b) = $self->HSVtoRGB($i, 1, 255);
		
		push(@gamma, {'red' => $r, 'green' => $g,'blue' => $b});
	}        
	return $self->draw_bar($data, $ranges, \@gamma, $TOP_LIMIT, $BOTTOM_LIMIT);
}

sub draw_model_scale_bar {
        my ($self, $data, $ranges) = @_;
        my @gamma = ();

        my $TOP_LIMIT = 5;
        my $BOTTOM_LIMIT = -5;

        my $MAX_HUE = 256;

        for(my $i = 0; $i < $MAX_HUE; $i++) {
                my ($r, $g, $b) = $self->HSVtoRGB($i, 1, 255);

                push(@gamma, {'red' => $r, 'green' => $g,'blue' => $b});
        }
        return $self->draw_scale_bar($data, $ranges, \@gamma, $TOP_LIMIT, $BOTTOM_LIMIT);
}



sub HSVtoRGB {
    my ($self, $hue, $saturation, $v) = @_;
    my ($red, $green, $blue);

    # If there's no saturation, then we're a grey
    unless ($saturation) {
            $red = $green = $blue = $v;
            return ($red, $green, $blue);
    }

    $hue /= 60;
    my $i = int( $hue );
    my $f = $hue - $i;
    my $p = $v * ( 1 - $saturation );
    my $q = $v * ( 1 - $saturation * $f );
    my $t = $v * ( 1 - $saturation * ( 1 - $f ) ); 


    if ($i == 0) { return( $v, $t, $p ) }
    elsif ($i == 1) { return( $q, $v, $p ) }
    elsif ($i == 2) { return( $p, $v, $t ) }
    elsif ($i == 3) { return( $p, $q, $v ) }
    elsif ($i == 4) { return( $t, $p, $v ) }
    else { return( $v, $p, $q ) } 
}

sub draw_bar {
	my ($self, $data, $ranges, $gamma, $TOP_LIMIT, $BOTTOM_LIMIT) = @_;
	
	my $DEFAULT_WIDTH = 500;
	my $DEFAULT_HEIGHT = 10;
	
	my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);
	
	my $color_white = $image->colorAllocate(255, 255, 255);

    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 209, 0); #ffd100
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000

    $image->transparent($color_white);
	$image->interlaced('true');
	
	my @color_gamma = ();
	
	for(my $i = 0; $i < scalar(@$gamma); $i++) {
		push(@color_gamma, $image->colorAllocate($$gamma[$i]{'red'}, $$gamma[$i]{'green'}, $$gamma[$i]{'blue'}));
	}

	my ($target_size) = $$ranges[scalar(@$ranges) - 1];

	my $step = ($target_size > 0) ? ($DEFAULT_WIDTH / $target_size) : 0;
	
	my $gamma_length = scalar(@color_gamma);

	for(my $i = 0; $i < scalar(@$data); $i++) {
		my $current_color = $color_white;
        #if(!($$data[$i] =~ /^([\-\.0-9]+)$/)) {
        #    $current_color = $color_white;
        #} elsif(($$data[$i] < $TOP_LIMIT) || ($$data[$i] > $BOTTOM_LIMIT)) {
        #    $current_color = $color_gamma[int($$data[$i] * $gamma_length / ($TOP_LIMIT + 1))];
        #} elsif($$data[$i] > $TOP_LIMIT) {
        #    $current_color = $color_gamma[255];
        #} elsif($$data[$i] < $BOTTOM_LIMIT) {
        #    $current_color = $color_gamma[0];
        #}

        if(!($$data[$i] =~ /^([\-\.0-9]+)$/)) {
            $current_color = $color_white;
        } elsif($$data[$i] <= -5) {
            $current_color = $color_darkblue;
        } elsif(($$data[$i] > -5) && ($$data[$i] <= -2)) {
            $current_color = $color_sky;
        } elsif(($$data[$i] > -2) && ($$data[$i] <= -0.5)) {
            $current_color = $color_green;
        } elsif(($$data[$i] > -0.5) && ($$data[$i] <= 0.5)) {
            $current_color = $color_yellow;
        } elsif(($$data[$i] > 0.5) && ($$data[$i] <= 2)) {
            $current_color = $color_orange;
        } elsif(($$data[$i] > 2) && ($$data[$i] <= 5)) {
            $current_color = $color_red;
        } elsif($$data[$i] >= 5) {
            $current_color = $color_darkred;
        }
		
		$image->filledRectangle($step*$i, 0, ($step + 1) * $i, $DEFAULT_HEIGHT - 1, $current_color);
	}
	
	return $image;
}


sub draw_scale_bar{
        my ($self, $data, $ranges, $gamma, $TOP_LIMIT, $BOTTOM_LIMIT) = @_;

        my $DEFAULT_WIDTH = 500;
        my $DEFAULT_HEIGHT = 10;

        my $image = new GD::Image($DEFAULT_WIDTH, $DEFAULT_HEIGHT);

        my $color_white = $image->colorAllocate(255, 255, 255);

    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 209, 0); #ffd100
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000

    $image->transparent($color_white);
        $image->interlaced('true');

        my @color_gamma = ();

        for(my $i = 0; $i < scalar(@$gamma); $i++) {
                push(@color_gamma, $image->colorAllocate($$gamma[$i]{'red'}, $$gamma[$i]{'green'}, $$gamma[$i]{'blue'}));
        }

#        my ($target_size) = $$ranges[scalar(@$ranges) - 1];
	my $first_res = $$ranges[0];
	my $last_res = $$ranges[scalar(@$ranges) - 1];
	my $target_size = $last_res - $first_res + 1;
	
        my $step = ($target_size > 0) ? ($DEFAULT_WIDTH / $target_size) : 0;

        my $gamma_length = scalar(@color_gamma);

        for(my $i = 0; $i < scalar(@$data); $i++) {
	if ($i + 1 < $first_res || $i + 1 > $last_res){next;}
        my $current_color = $color_white;
	if (in_array($i + 1, @$ranges)){
        #if(!($$data[$i] =~ /^([\-\.0-9]+)$/)) {
        #    $current_color = $color_white;
        #} elsif(($$data[$i] < $TOP_LIMIT) || ($$data[$i] > $BOTTOM_LIMIT)) {
        #    $current_color = $color_gamma[int($$data[$i] * $gamma_length / ($TOP_LIMIT + 1))];
        #} elsif($$data[$i] > $TOP_LIMIT) {
        #    $current_color = $color_gamma[255];
        #} elsif($$data[$i] < $BOTTOM_LIMIT) {
        #    $current_color = $color_gamma[0];
        #}

        if(!($$data[$i] =~ /^([\-\.0-9]+)$/)) {
            $current_color = $color_white;
        } elsif($$data[$i] <= -5) {
            $current_color = $color_darkblue;
        } elsif(($$data[$i] > -5) && ($$data[$i] <= -2)) {
            $current_color = $color_sky;
        } elsif(($$data[$i] > -2) && ($$data[$i] <= -0.5)) {
            $current_color = $color_green;
        } elsif(($$data[$i] > -0.5) && ($$data[$i] <= 0.5)) {
            $current_color = $color_yellow;
        } elsif(($$data[$i] > 0.5) && ($$data[$i] <= 2)) {
            $current_color = $color_orange;
        } elsif(($$data[$i] > 2) && ($$data[$i] < 5)) {
            $current_color = $color_red;
        } elsif($$data[$i] >= 5) {
            $current_color = $color_darkred;
        }
	}
                $image->filledRectangle($step*($i - $first_res), 0, $step*($i - $first_res + 1), $DEFAULT_HEIGHT - 1, $current_color);
        }

        return $image;
}

sub generate_dssp_image {
    my ($self, $ref_hash_align_data, $start, $end, $output_file_path) = @_;
    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 $width = $align_data_count * $step;
    my $height = 10;
    my $image = new GD::Image($width, $height);

    my $color_white     = $image->colorAllocate(255, 255, 255); #white
    my $color_ssH       = $image->colorAllocate(240,0,128); #f00080
    my $color_ssE       = $image->colorAllocate(255,255,0); #ffff00
    my $color_ssC       = $image->colorAllocate(96,128,255); #6080FF

    $image->transparent($color_white);
    $image->interlaced('true');
    $image->filledRectangle(0, 0, $width, $height, $color_white);

    for (my $i = 0; $i < $align_data_count; $i++) {
        my $color = $color_white;
        my $res = $i + $start;
	if (exists $align_data{$res} ){
		if ($align_data{$res} eq 'H') {
			$color = $color_ssH;
		} elsif ($align_data{$res} eq 'E') {
			$color = $color_ssE;
		} elsif ($align_data{$res} eq 'C') {
                        $color = $color_ssC;
                }
		$image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);
	}
    }
    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }
    return;
}

sub generate_diff_alignment_image {
    my ($self, $ref_hash_align_data, $start, $end, $metric, $output_file_path) = @_;
    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 $width = $align_data_count * $step;
    my $height = 10;
    my $image = new GD::Image($width, $height);
 
    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);

    my $color_white     = $image->colorAllocate(255, 255, 255);
    my $color_black     = $image->colorAllocate(0, 0, 0);
    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 153, 0); #ff9900
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000
    my $color_grey      = $image->colorAllocate(204, 204, 204);
    my $color_magenta   = $image->colorAllocate(204,51,204); #cc33cc

    $image->transparent($color_white);
    $image->interlaced('true');
    $image->filledRectangle(0, 0, $width, $height, $color_white);

    for(my $i = 0; $i < $align_data_count; $i++){
        my $color = $color_white;
        my $res = $i + $start;
        if (exists $align_data{$res} ){
           #if ($align_data{$res} >= 0.0){
              if ($metric eq 'lddt' ){
		if ($align_data{$res} <= -0.3) {
                   $color = $color_darkblue;
                } elsif ($align_data{$res} > -0.3 && $align_data{$res} <= -0.15) {
                   $color = $color_sky;
                } elsif ($align_data{$res} > -0.15 && $align_data{$res} <= -0.05) {
                   $color = $color_green;
                } elsif ($align_data{$res} > -0.05 && $align_data{$res} <= 0.05) {
                   $color = $color_yellow;
                } elsif ($align_data{$res} > 0.05 && $align_data{$res} <= 0.15) {
                   $color = $color_orange;
                } elsif ($align_data{$res} > 0.15 && $align_data{$res} <= 0.3) {
                   $color = $color_red;
                } elsif($align_data{$res} > 0.3) {
                   $color = $color_darkred;
                }
              } elsif ($metric eq 'gdt_ts'){
                if ($align_data{$res} <= -5.0) {
		   $color = $color_darkblue;
		} elsif ($align_data{$res} > -5.0 && $align_data{$res} <= -2.0) {
                   $color = $color_sky;
                } elsif ($align_data{$res} > -2.0 && $align_data{$res} <= -0.5) {
                   $color = $color_green;
                } elsif ($align_data{$res} > -0.5 && $align_data{$res} <= 0.5) {
                   $color = $color_yellow;
                } elsif ($align_data{$res} > 0.5 && $align_data{$res} <= 2.0) {
                   $color = $color_orange;
                } elsif ($align_data{$res} > 2.0 && $align_data{$res} <= 5.0) {
                   $color = $color_red;
                } elsif($align_data{$res} > 5.0) {
                   $color = $color_darkred;
                }
              } elsif ($metric eq 'sg_lvr' || $metric eq 'sg_py'){
                if ($align_data{$res} <= -2.5) {
                   $color = $color_darkblue;
                } elsif ($align_data{$res} > -2.5 && $align_data{$res} <= -1.5) {
                   $color = $color_sky;
                } elsif ($align_data{$res} > -1.5 && $align_data{$res} <= -0.5) {
                   $color = $color_green;
                } elsif ($align_data{$res} > -0.5 && $align_data{$res} <= 0.5) {
                   $color = $color_yellow;
                } elsif ($align_data{$res} > 0.5 && $align_data{$res} <= 1.5) {
                   $color = $color_orange;
                } elsif ($align_data{$res} > 1.5 && $align_data{$res} <= 2.5) {
                   $color = $color_red;
                } elsif($align_data{$res} > 2.5) {
                   $color = $color_darkred;
                }
              }
           #}
        }
        $image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);

    }
    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }
    return;

}

sub generate_alignment_image {
    my ($self, $ref_hash_align_data, $start, $end, $metric, $output_file_path) = @_;
    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 $width = $align_data_count * $step;
    my $height = 10;
    my $image = new GD::Image($width, $height);

    my $white = $image->colorAllocate(255, 255, 255);
    my $red = $image->colorAllocate(255, 0, 0);
    my $green = $image->colorAllocate(0, 255, 0);
    my $yellow = $image->colorAllocate(255, 255, 0);

    my $color_white     = $image->colorAllocate(255, 255, 255);
    my $color_black     = $image->colorAllocate(0, 0, 0);
    my $color_blue      = $image->colorAllocate(0, 184, 255); #00b8ff
    my $color_darkblue  = $image->colorAllocate(0, 0, 200); #0000c8
    my $color_sky       = $image->colorAllocate(0, 255, 250); #00fffa
    my $color_yellow    = $image->colorAllocate(255, 255, 0); #ffff00
    my $color_green     = $image->colorAllocate(0, 255, 0); #00ff00
    my $color_orange    = $image->colorAllocate(255, 153, 0); #ff9900
    my $color_red       = $image->colorAllocate(255, 105, 0); #ff6900
    my $color_darkred   = $image->colorAllocate(255, 0, 0); #ff0000
    my $color_grey      = $image->colorAllocate(204, 204, 204);
    my $color_magenta   = $image->colorAllocate(204,51,204); #cc33cc

    $image->transparent($color_white);
    $image->interlaced('true');
    $image->filledRectangle(0, 0, $width, $height, $color_white);

    for(my $i = 0; $i < $align_data_count; $i++){
        my $color = $color_white;
        my $res = $i + $start;
        if (exists $align_data{$res} ){
           if ($align_data{$res} >= 0.0){
              if ($metric eq 'lddt'){
                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;
                }
              } elsif ($metric eq 'sg_lvr' || $metric eq 'sg_py'){
                if ($align_data{$res} >= 40.0) {
                   $color = $color_sky;
                } elsif ($align_data{$res} >= 20.0) {
                   $color = $color_green;
                } elsif ($align_data{$res} >= 10.0) {
                   $color = $color_yellow;
                } elsif ($align_data{$res} >= 5.0) {
                   $color = $color_orange;
                } else {
                   $color = $color_darkred;
                }
              }
           }
        }
        $image->filledRectangle($i*$step, 1, ($i + 1)*$step, $height - 1, $color);

    }
    if (open FILE, "+>", $output_file_path) {
        print FILE $image->png;
        close(FILE);
    }
    return;
}


1;
