-
Notifications
You must be signed in to change notification settings - Fork 21
/
NameHandler.pm
113 lines (77 loc) · 2.39 KB
/
NameHandler.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
=head1 NAME
NameHandler - create indices of feature names
=head1 SYNOPSIS
# instantiate with a callback that gives the directory to use for a
# given reference sequence
my $nameHandler = NameHandler->new(
sub { "$trackDir/" . $_[0] . "/" . $track->{"track"}; };
);
for my $name ( @feature_names ) {
$nameHandler->addName( $name );
}
# write out the finished names index
$nameHandler->finish;
=head1 METHODS
=cut
package NameHandler;
use strict;
use warnings;
use Carp;
use File::Path;
use IO::File;
use JSON 2;
# index of the refseq name in the name array
# TODO: find a central place to put this knowledge
our $chromIndex = 3;
my $nameFile = "names.txt";
=head1 new( \&directory_callback )
Make a new NameHandler. Takes a subroutine reference that should take
a reference sequence name as an argument and return the path to the
directory that should contain the name index we generate.
=cut
sub new {
my ($class, $trackDirForChrom) = @_;
my $self = {
trackDirForChrom => $trackDirForChrom,
nameFiles => {}
};
bless $self, $class;
return $self;
}
=head1 addName( \@name_record )
Name record (an arrayref) to add to the names index.
=cut
sub addName {
my ($self, $nameArr) = @_;
my $chrom = $nameArr->[$chromIndex];
unless (defined($chrom)) {
carp "chrom not defined in " . JSON::to_json($nameArr) . "\n";
}
my $nameFile = $self->{nameFiles}->{$chrom} ||= $self->_newChrom($chrom);
$nameFile->print( JSON::to_json( $nameArr, {pretty => 0} ), "\n" )
or die "couldn't write to file for $chrom: $!";
}
# Given the name of the reference sequence, opens and returns a filehandle to the
# proper name index file. Makes a new directory to hold the file if
# necessary.
sub _newChrom {
my ($self, $chrom) = @_;
my $chromDir = $self->{trackDirForChrom}->($chrom);
mkpath( $chromDir ) unless -e $chromDir;
my $namefile = "$chromDir/$nameFile";
my $fh = IO::File->new( $namefile, '>' ) or die "$! writing $namefile";
return $fh;
}
=head1 finish
Finalize and flush to disk any currently open name index.
=cut
sub finish {
my ($self) = @_;
foreach my $chrom (keys %{$self->{nameFiles}}) {
my $fh = $self->{nameFiles}->{$chrom};
if( $fh && $fh->opened ) {
$fh->close or die "$! closing names file for ref seq $chrom";
}
}
}
sub DESTROY { shift->finish }