Repository navigation
Expand file tree
/
Copy pathorthofinder_selectGroups.pl
More file actions
executable file
·178 lines (158 loc) · 5.58 KB
/
Copy pathorthofinder_selectGroups.pl
File metadata and controls
executable file
·178 lines (158 loc) · 5.58 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/env perl
## author: reubwn October 2016
use strict;
use warnings;
use Bio::Seq;
use Bio::SeqIO;
use Getopt::Long;
use Sort::Naturally;
use File::Path 'rmtree';
my $usage = "
SYNOPSIS:
Parses Orthofinder output file \"Orthogroups.txt\" for groups corresponding to input criteria.
Construct the 'select' string like so: \"ID1=X,ID2=Y,IDN=Z\", where ID1 is the unique species ID
corresponding to the entity on the lefthandside of the delimiter given by -d (default is '|'), and
X is the number of members from species 1 you want to select groups containing.
OUTPUTS:
A file \"selectGroups_output.groups.txt\" with only selected groups written, and a directory \"selectGroups_outputDir/\"
with fasta files containing sequence data of selected groups.
OPTIONS:
-i|--in [FILE] : Orthogroups.txt file [required]
-f|--fasta [FILE] : path to directory of fasta files used to construct Orthogroups.txt [required]
-d|--delim [STR] : delimiter used in the protein naming structure [assumes an OrthoMCL-style schema of \"SPECIES_ID|PROTEIN_ID\"]
-s|--select [STR] : select string, eg. \"ID1=1,ID2=1,IDN=1\" would return 1:1 orthologous groups
-n|--noseqs : don't print sequences; just count the groups
-y|--only : only print those sequences represented in the --select string (ignores anything else in selected OGs)
-o|--out [STR] : output prefix [default: orthofinder_selectGroups]
-h|--help : prints this help message
EXAMPLES:
Select ONLY those groups where species ARIC and AVAG have 4 members each, and species RMAG and RMAC have 2 members each:
>> ./orthofinder_selectGroups.pl -i Orthogroups.txt -f fastas/ -s \"ARIC=4,AVAG=4,RMAG=2,RMAC=2\"
\n";
my ($in,$fastas,$select,$noseqsplease,$only,$out,$help);
my $prefix = "selectGroups_output";
my $delim = "|";
GetOptions (
'i|in=s' => \$in,
'f|fastas=s' => \$fastas,
'd|delim:s' => \$delim,
's|select=s' => \$select,
'n|noseqs' => \$noseqsplease, ## :-)
'y|only' => \$only,
'o|out:s' => \$prefix,
'h|help' => \$help,
);
die $usage if $help;
die $usage unless ($in && $fastas && $select);
## construct outfiles
open (my $GROUPS, ">".$prefix.".selected.txt") or die "$!\n";
## parse select string
my %select_hash;
my @a = split(",",$select);
foreach (@a){
my @b = split("=",$_);
$select_hash{$b[0]} = $b[1]; ## key= SPECIES_ID; value= PER_SPECIES_GROUP_SIZE
}
print "Select per-species group sizes:\n";
foreach (nsort keys %select_hash){
print " $_\t$select_hash{$_}\n";
}
print "\n";
## get sequences
my %seq_hash;
unless ($noseqsplease){ ## skip if just counting
my @fastas = glob("$fastas*fasta");
if (scalar(@fastas) == 0) {
print "Nothing found in $fastas with *.fasta... will try *.faa\n";
@fastas = glob("$fastas*faa");
}
if (scalar(@fastas) == 0) {
print "Nothing found in $fastas with *.faa... will try *.fna\n";
@fastas = glob("$fastas*fna");
}
if (scalar(@fastas) == 0) {
print "Nothing found in $fastas with *.fna... will try *.aa (augustus style)\n";
@fastas = glob("$fastas*aa");
}
if (scalar(@fastas) == 0) {
die "Still nothing found in $fastas\nPlease make sure there are protein fastas in $fastas with extension fasta|faa|fna|aa\n";
}
print "Reading sequences from:\n";
foreach (@fastas){
print " $_\n";
my $in = Bio::SeqIO->new ( -file => $_, -format => "fasta" );
while ( my $seq_obj = $in->next_seq() ){
$seq_hash{($seq_obj->display_id())} = ($seq_obj->seq());
}
}
print "Read in ".commify(scalar(keys %seq_hash))." sequences from ".commify(scalar(@fastas))." files\n\n";
} else {
print "Skipping fetching sequences, just counting\n";
}
## parse OrthologousGroups.txt
my %groups_hash;
open(my $IN, $in) or die "Error! Could not open $in: $!\n";
while (my $line = <$IN>){
chomp $line;
my @a = split(/\:\s+/,$line);
my @b = split(/\s+/,$a[1]);
my %g;
foreach (@b){
my @c = split(/\|/,$_);
$g{$c[0]}++; ##count per-species membership for group
}
my $flags = 0;
foreach (nsort keys %g){
## if the group contains the SPECIES_ID of interest and has the specified number of members
if (($select_hash{$_}) && ($g{$_} == $select_hash{$_})) {
$flags++;
}
}
## only print if all SPECIES_ID criteria are met
if ($flags == scalar(keys %select_hash)) {
$groups_hash{$a[0]} = \@b;
print $GROUPS "$line\n"; ## print selected groups to new groups file
}
}
close $GROUPS;
print "Found ".commify(scalar(keys %groups_hash))." groups satisfying select criteria\n";
unless ($noseqsplease) {
## mkdir for OG fastas
my $dir = $prefix."_fasta";
if (-e $dir && -d $dir) {
rmtree([ "$dir" ]);
mkdir $dir;
chdir $dir;
} else {
mkdir $dir;
chdir $dir;
}
## fetch sequence data for selected groups
print "Printing sequence data per selected group in $dir/\n";
print "Only printing sequences for species containing ".join(" ",keys %select_hash)."\n" if $only;
foreach (nsort keys %groups_hash) {
open (my $SEQS, ">$_.fasta") or die "$!\n";
my @seqs = @{$groups_hash{$_}};
if ($only) {
## only print the seqs from the species represented in the select string
foreach my $seqid (@seqs) {
foreach my $wanted (keys %select_hash) {
print $SEQS "\>$seqid\n$seq_hash{$seqid}\n" if ($seqid =~ /$wanted/);
}
}
} else {
foreach my $seqid (@seqs) {
print $SEQS "\>$seqid\n$seq_hash{$seqid}\n";
}
}
close $SEQS;
}
}
print "\n";
######################## SUBS
sub commify {
my $text = reverse $_[0];
$text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
return scalar reverse $text;
}
__END__