Bio-BigFile
view release on metacpan or search on metacpan
lib/Bio/DB/BigWigSet.pm view on Meta::CPAN
}
# create a lazy loading bigwig for each file
for my $file (@$wigfiles) {
$self->add_bigwig($file);
my $name = basename($file,'.bw');
$self->set_bigwig_attributes($file,
{
display_name=>$name,
dbid =>$file,
});
}
# read the tables of attributes
for my $file (@$indices) {
$self->read_index($file,$dir);
}
}
sub read_local_dir {
my $self = shift;
my $dir = shift;
croak "directory $dir doesn't exist" unless -d $dir;
croak "directory $dir not readable" unless -r _;
my (@indices,@wigfiles);
my $d = IO::Dir->new($dir);
while (my $node = $d->read) {
next if $node =~ /^[.#]/; # dot files and temp files
next if $node =~ /~$/; # autosave files
my $file = File::Spec->catfile($dir,$node);
next unless -f $file;
if ($node =~ /^meta/) {
push @indices,$file;
} elsif ($node =~ /\.bw/i) {
push @wigfiles,$file;
}
}
undef $d;
return (\@wigfiles,\@indices);
}
sub read_remote_dir {
my $self = shift;
my $dir = shift;
eval "require LWP::UserAgent;1" or die "LWP is required to handle remote directories"
unless LWP::UserAgent->can('new');
eval "require URI::URL;1" or die "URI::URL is required to handle remote directories"
unless URI::URL->can('new');
my $ua = LWP::UserAgent->new;
my $response = $ua->get($dir,Accept=>'text/html, */*;q=0.1');
unless ($response->is_success) {
warn "Web fetch of $dir failed: ",$response->status_line;
return;
}
my $html = $response->decoded_content;
my $base = $response->base;
my @wigfiles = map {URI::URL->new($_=>$base)->abs} $html =~ /href="([^\"]+\.bw)"/ig;
my @indices = map {URI::URL->new($_=>$base)->abs} $html =~ /href="(meta[^\"]*)"/ig;
return (\@wigfiles,\@indices);
}
=item $bws->add_bigwig($path)
Given a path to a .bw file, add the BigWig file to the set.
=cut
sub add_bigwig {
my $self = shift;
my $path = shift;
$self->{bigwigs}{$path} = undef; # lazy loading
}
=item $bws->remove_bigwig($path)
Given a path to a .bw file, removes it from the set.
=cut
sub remove_bigwig {
my $self = shift;
my $path = shift;
delete $self->{bigwigs}{$path};
delete $self->{attributes}{$path};
}
=item $bws->set_bigwig_attributes($path,$attributes)
Given the path to a BigWig file, assign metadata to it. The second
argument is a hash in which the keys are attribute names such as
"type" and the values are the values of those attributes.
If the BigWig file is not already part of the set, it is added (as in
add_bigwig()).
=cut
sub set_bigwig_attributes {
my $self = shift;
my ($path,$attributes) = @_;
if (my $old = $self->{attributes}{$path}) {
%$attributes = (%$old,%$attributes); # merge
}
$self->{bigwigs}{$path} ||= undef;
$self->{attributes}{$path} = $attributes;
}
=item @paths = $bws->bigwigs
Returns the path to all the BigWig files in the collection.
=cut
sub bigwigs {
my $self = shift;
return keys %{$self->{bigwigs}};
}
=item $bigwig = $bws->get_bigwig($path)
If the BigWig file is part of the set, opens and returns it.
=back
=cut
sub get_bigwig {
my $self = shift;
my $path = shift;
return unless exists $self->{bigwigs}{$path};
my $bw = $self->{bigwigs}{$path} ||=
Bio::DB::BigWig->new(-bigwig => $path,
-fasta => $self->dna_accessor||undef)
or die "Could not open bigwig file $path: $!";
return $bw;
}
sub read_index {
my $self = shift;
my ($file,$base) = @_;
$base ||= dirname($file);
my $f;
if ($file =~ /^(ftp|http):/i) {
my $ua = LWP::UserAgent->new;
my $r = $ua->get($file);
die "Couldn't read $file: ",$r->status_line unless $r->is_success;
eval "require IO::String; 1"
or die "IO::String module is required for remote directories"
unless IO::String->can('new');
$f = IO::String->new($r->decoded_content);
}
else {
$f = IO::File->new($file) or die "$file: $!";
}
my ($current_path,%wigs);
while (<$f>) {
chomp;
s/\s+$//; # strip whitespace at ends of lines
# 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 (/^\[([^\]]+)\]/) { # beginning of a configuration section
my $wigname = $1;
$current_path = $wigname =~ m!^(/|http:|ftp:)! ? $wigname
: "$base/$wigname";
}
elsif ($current_path && /^([\w: -]+?)\s*=\s*(.*)/) { # key value pair
my $tag = lc $1;
my $value = defined $2 ? $2 : '';
$wigs{$current_path}{$tag}=$value;
}
}
for my $path (keys %wigs) {
my $attributes = $wigs{$path};
$self->set_bigwig_attributes($path,$attributes);
}
}
sub segment {
my $self = shift;
my ($seqid,$start,$end) = @_;
if ($_[0] =~ /^-/) {
my %args = @_;
$seqid = $args{-seq_id} || $args{-name};
$start = $args{-start};
$end = $args{-stop} || $args{-end};
} else {
($seqid,$start,$end) = @_;
}
my ($one_bigwig) = keys %{$self->{bigwigs}};
my $bw = $self->get_bigwig($one_bigwig);
my $size = $bw->length($seqid) or return;
$start ||= 1;
$end ||= $bw->length($seqid);
return unless $start >= 1 && $start < $size;
return unless $end >= 1 && $end < $size;
return Bio::DB::BigWigSet::Segment->new(-bws => $self,
-seq_id=> $seqid,
-start => $start,
-end => $end);
}
( run in 0.885 second using v1.01-cache-2.11-cpan-39bf76dae61 )