Bio-Graphics
view release on metacpan or search on metacpan
lib/Bio/Graphics/FeatureFile.pm view on Meta::CPAN
appears.
=head2 Feature Tags
Tags can be added to features by adding a fourth column consisting of
"tag=value" pairs:
Gene B0511.1 Chr1:516..619,3185..3294 Note="Putative primase"
Tags and their values take any form you want, and multiple tags can be
separated by semicolons. You can also repeat tags multiple times:
Gene B0511.1 Chr1:516..619,3185..3294 GO_Term=GO:100;GO_Term=GO:2087
Several tags have special meanings:
Tag Meaning
--- -------
Type The primary tag for a subfeature.
Score The score of a feature or subfeature.
Phase The phase of a feature or subfeature.
URL A URL to link to (via the Bio::Graphics library).
Note A note to attach to the feature for display by the Bio::Graphics library.
For example, in the common case of an mRNA, you can use the "Type" tag
to distinguish the parts of the mRNA into UTR and CDS:
mRNA B0511.1 Chr1:1..100 Type=UTR
mRNA B0511.1 Chr1:101..200,300..400,500..800 Type=CDS
mRNA B0511.1 Chr1:801..1000 Type=UTR
The top level feature's primary tag will be "mRNA", and its subparts
will have types UTR and CDS as indicated. Additional tags that are
placed in the first line of the feature will be applied to the top
level. In this example, the note "Putative primase" will be applied to
the mRNA at the top level of the feature:
mRNA B0511.1 Chr1:1..100 Type=UTR;Note="Putative primase"
mRNA B0511.1 Chr1:101..200,300..400,500..800 Type=CDS
mRNA B0511.1 Chr1:801..1000 Type=UTR
=head2 Feature Groups
Features can be grouped so that they are rendered by the "group"
glyph. To start a group, create a two-column feature entry showing
the group type and a name for the group. Follow this with a list of
feature entries with a blank type. For example:
EST yk53c10
yk53c10.3 15000-15500,15700-15800
yk53c10.5 18892-19154
This example is declaring that the ESTs named yk53c10.3 and yk53c10.5
belong to the same group named yk53c10.
=head2 Comments
Lines that begin with the # sign are treated as comments and
ignored. When a # sign appears within a line, everything to the right
of the symbol is also ignored, unless it looks like an HTML fragment or
an HTML color, e.g.:
# this is ignored
[Example]
glyph = generic # this comment is ignored
bgcolor = #FF0000
link = http://www.google.com/search?q=$name#results
Be careful, because the processing of # signs uses a regexp heuristic. To be safe,
always put a space after the # sign to make sure it is treated as a comment.
=head2 The #include and #exec Directives
The special comment "#include 'filename'" acts like the C preprocessor
directive and will insert the comments of a named file into the
position at which it occurs. Relative paths will be treated relative
to the file in which the #include occurs. Nested #include directives
(a #include located in a file that is itself an include file) are
#allowed. You may also use one of the shell wildcard characters * and
#? to include all matching files in a directory.
The following are examples of valid #include directives:
#include "/usr/local/share/my_directives.txt"
#include 'my_directives.txt'
#include chromosome3_features.gff3
#include gff.d/*.conf
You can enclose the file path in single or double quotes as shown
above. If there are no spaces in the filename the quotes are optional.
The #include directive is case insensitive, allowing you to use
#INCLUDE or #Include if you prefer.
Include file processing is not very smart and will not catch all
circular #include references. You have been warned!
The special comment "#exec 'command'" will spawn a shell and
incorporate the output of the command into the configuration
file. This command will be executed quite frequently, so it is
suggested that any time-consuming processing that does not need to be
performed on the fly each time should be cached in a local file.
=cut
use strict;
use Bio::Graphics::Feature;
use Bio::DB::GFF::Util::Rearrange;
use Carp 'cluck','carp','croak';
use IO::File;
use File::Glob ':glob';
use Text::ParseWords 'shellwords';
use Bio::DB::SeqFeature::Store;
use File::Basename 'dirname';
use File::Spec;
use Cwd 'getcwd';
# default colors for unconfigured features
my @COLORS = qw(cyan blue red yellow green wheat turquoise orange);
# package variable which holds the limited set of libraries accessible
lib/Bio/Graphics/FeatureFile.pm view on Meta::CPAN
}
if (/^#exec\s+(.+)/i) { # #exec directive
my ($command,@args) = shellwords($1);
open (my $fh,'-|') || exec $command,@args;
$self->parse_fh($fh);
return 1;
}
return 1 if $line =~ /^\s*\#[^\#]?$/; # comment line
# Are we in a configuration section or a data section?
# We start out in 'config' state, and are triggered to
# reenter config state whenever we see a /^\[ pattern (config section)
my $old_state = $self->{state};
my $new_state = $self->_state_transition($line);
if ($new_state ne $old_state) {
delete $self->{current_config};
delete $self->{current_tag};
}
if ($new_state eq 'config') {
$self->parse_config_line($line);
} elsif ($new_state eq 'data') {
$self->parse_data_line($line);
}
$self->{state} = $new_state;
1;
}
sub _state_transition {
my $self = shift;
my $line = shift;
my $current_state = $self->{state};
if ($current_state eq 'data') {
return 'config' if $line =~ m/^\s*\[([^\]]+)\]/; # start of a configuration section
}
elsif ($current_state eq 'config') {
return 'data' if $line =~ /^\#\#(\w+)/; # GFF3 meta instruction
return 'data' if $line =~ /^reference\s*=/; # feature-file reference sequence directive
return 'config' if $line =~ /^\s*$/; #empty line
return 'config' if $line =~ m/^\[(.+)\]/; # section beginning
return 'config' if $line =~ m/^[\w:\s]+=/
&& $self->{current_config}; # configuration line
return 'config' if $line =~ m/^\s+(.+)/
&& $self->{current_tag}; # continuation section
return 'config' if $line =~ /^\#/; # comment -not a meta
return 'data';
}
return $current_state;
}
sub parse_config_line {
my $self = shift;
local $_ = shift;
# strip right-column comments unless they look like colors or html fragments
s/\s*\#.*$// unless /\#[0-9a-f]{6,8}\s*$/i || /\w+\#\w+/ || /\w+\"*\s*\#\d+$/;
if (/^\s+(.+)/ && $self->{current_tag}) { # configuration continuation line
my $value = $1;
my $cc = $self->{current_config} ||= 'general'; # in case no configuration named
$self->{config}{$cc}{$self->{current_tag}} .= ' ' . $value;
# respect newlines in code subs
$self->{config}{$cc}{$self->{current_tag}} .= "\n"
if $self->{config}{$cc}{$self->{current_tag}}=~ /^sub\s*\{/;
return 1;
}
elsif (/^\[(.+)\]/) { # beginning of a configuration section
my $label = $1;
my $cc = $label =~ /^(general|default)$/i ? 'general' : $label; # normalize
push @{$self->{types}},$cc unless $cc eq 'general';
$self->{current_config} = $cc;
return 1;
}
elsif (/^([\w: -]+?)\s*=\s*(.*)/) { # key value pair within a configuration section
my $tag = lc $1;
my $cc = $self->{current_config} ||= 'general'; # in case no configuration named
my $value = defined $2 ? $2 : '';
$self->{config}{$cc}{$tag} = $value;
$self->{current_tag} = $tag;
return 1;
}
elsif (/^$/) { # empty line
# no longer required -- new sections are indicated by the start of a [stanza]
# line and not by termination with a blank line
# undef $self->{current_tag};
return 1;
}
}
sub parse_data_line {
my $self = shift;
my $line = shift;
$self->{loader} ||= $self->_make_loader($line) or return;
$self->{loader}->load_line($line);
}
sub _make_loader {
my $self = shift;
local $_ = shift;
my $db = $self->db;
my $type;
# we support gff2, gff3 and featurefile formats
if (/^\#\#gff-version\s+([23])/) {
$type = "Bio::DB::SeqFeature::Store::GFF$1Loader";
}
elsif (/^reference\s*=.+/) {
$type = "Bio::DB::SeqFeature::Store::FeatureFileLoader";
}
( run in 0.635 second using v1.01-cache-2.11-cpan-364913b4093 )