Bio-BioStudio

 view release on metacpan or  search on metacpan

bin/BS_Cartoonist.pl  view on Meta::CPAN


die ("BSERROR: Factor must be at least 2.\n")
  if ($p{FACTOR} && $p{FACTOR} < 2);

################################################################################
################################# CONFIGURING ##################################
################################################################################
my $chrseq = $chr->sequence;
my $chrlen = length $chrseq;

my @features = $chr->db->features;

$p{DATAEND} = $p{DATAEND} && $p{DATAEND} <= $chrlen
              ? $p{DATAEND}
              : $chrlen;
$p{DATASTART} = $p{DATASTART} && $p{DATASTART} >= 1 && $p{DATASTART} < $p{DATAEND}
              ? $p{DATASTART}
              : 1;

#Scaling factor
$p{FACTOR} = $p{FACTOR} ? $p{FACTOR} : 10;

#PDF margins
$p{LEFT_MARGIN} = 100;
$p{RIGHT_MARGIN} = 100;

#Each level represent 50kb of data, with a height of 400
$p{LEVEL_WIDTH} = $p{LEVEL_WIDTH} ? $p{LEVEL_WIDTH}  : 50000;
$p{LEVEL_HEIGHT} = 460;

#Left Freedom Data: amount of data that will repeat from the last line
$p{LEFT_REPEAT} = $p{LEFT_REPEAT} ? $p{LEFT_REPEAT}  : 1000; # 1000 = 1kb @ factor 10
$p{LEFT_REP_WIDTH} = int($p{LEFT_REPEAT} / $p{FACTOR});
$p{LEFT_DATA_MARGIN} = $p{LEFT_MARGIN} + $p{LEFT_REP_WIDTH};

#Right Freedom Data: amount of data that will repeat on the next line
$p{RIGHT_REPEAT} = $p{RIGHT_REPEAT} ? $p{RIGHT_REPEAT} : 1000; # 1000 = 1kb @ factor 10
$p{RIGHT_REP_WIDTH} = int($p{RIGHT_REPEAT} / $p{FACTOR});

#Scale Height and Width
$p{SCALE_HEIGHT} = 150;
$p{SCALE_WIDTH} = int($p{LEVEL_WIDTH} / $p{FACTOR}) + $p{LEFT_REP_WIDTH} + $p{RIGHT_REP_WIDTH};
$p{SCALE_LENGTH} = $p{SCALE_WIDTH}-$p{RIGHT_REP_WIDTH}-$p{LEFT_REP_WIDTH};

#intial feature y position and y distance between W/C strands
$p{STRAND_Y_POS} = 245;
$p{STRAND_DISTANCE} = 70;

$p{FEAT_RGB} = parse_colors();

$p{U_BIG_SCALE_MARK} = ceil(.2*$p{LEVEL_WIDTH});

my %drawing = ("stop_retained_variant" => 1, "CDS" => 1, "PCR_product" => 1,
  "centromere" => 1, "ARS" => 1, "restriction_enzyme_recognition_site" => 1,
  "enzyme_recognition_site" => 1,
  "site_specific_recombination_target_region" => 1, "intron" => 1,
  "repeat_family" => 1, "universal_telomere_cap" => 1, "deletion" => 1);
 
my %labeling = ("gene" => 1, "centromere" => 1, "ARS" => 1);

my %legending = (
  "stop_retained_variant" => "stop swap",
  "PCR_product" => "PCRTag amplicon",
  "ARS" => "ARS",
  "intron" => 0, "centromere" => 0,
  "universal_telomere_cap" => "Telomere seed sequence",
  "site_specific_recombination_target_region" => "loxPsym site",
  "repeat_family" => 0,
  "deletion" => 0,
  "CDS" => 0
);

################################################################################
################################### Drawing ####################################
################################################################################
my $width = int($p{LEFT_MARGIN} + $p{RIGHT_MARGIN} + $p{SCALE_WIDTH});
my $height = ceil(($p{DATAEND} - $p{DATASTART}) / $p{LEVEL_WIDTH}) * $p{LEVEL_HEIGHT};
my $filename = $chr->name . ".pdf";
my $outputloc = $filename;

my $surface = Cairo::PdfSurface->create($outputloc, $width, $height)
  || croak "$OS_ERROR";
my $ctx = Cairo::Context->create($surface);

#Set fonts
my $fonts = parse_fonts();
my $fontfile = $fonts->{Inconsolata};
my $ftfont = Font::FreeType->new->face($fontfile);
my $fontface = Cairo::FtFontFace->create($ftfont);
$ctx->set_font_face($fontface);
my $fontsize = 500 / $p{FACTOR};
$fontsize = 7 if ($fontsize < 7);
$ctx->set_font_size($fontsize);

#Draw white background
$ctx->set_source_rgb(1, 1, 1);
$ctx->rectangle(0, 0, $width, $height);
$ctx->fill;


#Draw backbone and scale marks
$p{LEVEL_COUNT} = draw_scale($ctx, \%p);
$ctx->set_line_width(5);

#Draw name of file
$ctx->save();
my $thref = $ctx->text_extents($chr->name);
$ctx->move_to($p{LEFT_MARGIN} / 2, $height / 2 + ($thref->{width} / 2));
$ctx->rotate(-1.57079633);
$ctx->show_text($chr->name);
$ctx->restore();

#length of the Last level
my $LastScaleMidLen = fmod(($p{DATAEND} - $p{DATASTART}), $p{LEVEL_WIDTH}) / $p{FACTOR};

#Set font Size for other feature (Restriction Enzymes)
my $fontSize = 450 / $p{FACTOR};
$fontSize = 20 if ($fontSize < 20);
$ctx->set_font_size ($fontSize);

$p{FEATURES} = {};

bin/BS_Cartoonist.pl  view on Meta::CPAN

    if ($i == $p{LEVEL_COUNT})
    {
      $midEnd = $p{LEFT_DATA_MARGIN} + $LastScaleMidLen;
      $rightEnd = $p{LEFT_DATA_MARGIN} + $LastScaleMidLen + $p{RIGHT_REP_WIDTH};
    }
    $obj->{DrawStart} = $obj->{scaledStart} - ($i - $obj->{LevelNumStart}) * $p{SCALE_LENGTH};
    $obj->{DrawEnd} = $obj->{scaledEnd} + ($obj->{LevelNumEnd} - $i) * $p{SCALE_LENGTH};
    $obj->{LevelNum} = $i;
    #Draw left freedom dashed,
    if ($obj->{DrawStart} <= $p{LEFT_DATA_MARGIN})
    {
      draw_feature($ctx, $obj, $p{LEFT_MARGIN}, $p{LEFT_DATA_MARGIN}, 1, \%p);
    }
    #Draw middle solid
    if ($obj->{DrawStart} <= $midEnd) #&& $obj->{DrawEnd} >= $p{LEFT_DATA_MARGIN}
    {
      draw_feature($ctx, $obj, $p{LEFT_DATA_MARGIN}, $midEnd, 0, \%p);
    }
    #Draw right freedom dashed
    if ($obj->{DrawEnd} >= $midEnd || $obj->{LevelNumStart} > $i)
    {
      draw_feature($ctx, $obj, $midEnd, $rightEnd, 1, \%p);
    }
  }
}

$surface->flush();
$surface->finish();


#Draw Labels and Key
my $lloc =  q{./} . $chr->name . "_key.pdf";
my $lsurface = Cairo::PdfSurface->create($lloc, $width, $height) || croak $OS_ERROR;
my $key = Cairo::Context->create($lsurface);
$key->set_font_face($fontface);
$key->set_font_size ($fontSize);

my @labellist = grep {exists $labeling{$_->primary_tag}} @labels;
my $y = 200;
my $x = 500;
#Draw Feature Labels
foreach my $feat (sort {$a->start <=> $b->start} @labellist)
{
  my $text = $feat->Tag_load_id;
  my $thref = ($key->text_extents($text));
  if ($x + $thref->{width} > $width)
  {
    $x = 500;
    $y = $y+100;
  }
  my $tx = $x - $thref->{width}/2;
  $key->move_to($tx, $y);
  $key->show_text($text);
  $y = ($x+(2*$thref->{width}) > $width - 500)  ? $y+100 : $y + 2;
  $x = ($x+(2*$thref->{width}) > $width - 500)  ? 500 : $x+(2*$thref->{width});
}

#Draw Key
$x = 500;
$y += 100;
foreach my $type (grep {exists $legending{$_}} keys %index)
{
  print "got a $type!\n";
  my %objs;
  if ($type eq 'CDS')
  {
    my @CDSes = @{$index{$type}};
    if ($CDSes[0]->{feat}->has_tag('essential_status') && $CDSes[0]->{feat}->has_tag('orf_classification'))
    {
      $objs{"essential ORF"} = first {$_->{feat}->Tag_essential_status eq "Essential"} @{$index{$type}};
      $objs{"slow growth ORF"} = first {$_->{feat}->Tag_essential_status eq "fast_growth"} @{$index{$type}};
      $objs{"non-essential ORF"} = first {$_->{feat}->Tag_orf_classification eq "Verified"} @{$index{$type}};
      $objs{"uncharacterized ORF"} = first {$_->{feat}->Tag_orf_classification eq "Uncharacterized"} @{$index{$type}};
      $objs{"dubious ORF"} = first {$_->{feat}->Tag_orf_classification eq "Dubious"} @{$index{$type}}; 
    }
    else
    {
      $objs{"ORF"} = $CDSes[0];
    }
  }
  else
  {
    $objs{$type} = first {1} @{$index{$type}};
  }
  foreach my $text (keys %objs)
  {
    my $xywref = [$x, $y, 50];
    my $obj = $objs{$text};
    $text = $legending{$type} if ($legending{$type});
    print "keying $text\n";
    my $thref = ($key->text_extents($text));
    my $xbeg = $p{LEFT_MARGIN};
    my $xend = $p{LEFT_DATA_MARGIN} + $LastScaleMidLen + $p{RIGHT_REP_WIDTH};
    draw_feature($key, $obj, $xbeg, $xend, 0, \%p, $xywref);
    $key->move_to($x + 50 + ($thref->{width} / 2), $y);
    $key->show_text($text);
    $y = $y + 100;
    $x = 500;
  }
}
$lsurface->flush();
$lsurface->finish();

print "See " . q{./} . $chr->name . ".pdf\n\n";

exit;

__END__

=head1 NAME

  BS_Cartoonist.pl

=head1 VERSION

  Version 2.10

=head1 DESCRIPTION

  This utility takes a chromosome from the BioStudio genome repository and makes
   a vector image of its annotations.

=head1 ARGUMENTS

Required arguments:

  -C, --CHROMOSOME : The chromosome to be rendered.  Must be in the BioStudio
    genome repository.
 
Optional arguments:

  -F, --FACTOR : [def 10] The factor by which data will be scaled. Must be at
      least 2 - do you really want a 1:1 diagram of a chromosome?
  -L, --LEVELWIDTH : [def 50000] The bases represented per level of the diagram.
      A width of 50000 with a scaling factor of 10 will result in an image about
      5000 pixels wide.
  --REPEATLEFT : [def 1000] The number of bases from the previous level of the
      diagram that will be repeated in dashed lines, on the next level.
  --REPEATRIGHT : [def 1000] The number of bases at the end of each level of the
      diagram that will be repeated in dashed lines, on the next level.
  --START : [def 1] The first base to be displayed in the diagram. If it is not
      less than the length and equal to or greater than 1, it will default to 1.
  --STOP : [def chromosome length] The last base to be displayed in the
      diagram. If this number is larger than the length of the chromosome, it
      will default to chromosome length.
  -h, --help : Display this message
 
=head1 COPYRIGHT AND LICENSE



( run in 0.644 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )