File Coverage

blib/lib/BioX/Wrapper/Gemini.pm
Criterion Covered Total %
statement 27 126 21.4
branch 0 24 0.0
condition 0 3 0.0
subroutine 9 15 60.0
pod n/a
total 36 168 21.4


line stmt bran cond sub pod time code
1             package BioX::Wrapper::Gemini;
2              
3 1     1   22658 use 5.008_005;
  1         4  
  1         61  
4              
5             our $VERSION = '0.05';
6              
7 1     1   728 use Moose;
  1         397611  
  1         6  
8 1     1   6266 use File::Find::Rule;
  1         6624  
  1         7  
9 1     1   45 use File::Basename;
  1         1  
  1         69  
10 1     1   5 use File::Path qw(make_path remove_tree);
  1         1  
  1         44  
11 1     1   5 use File::Find::Rule;
  1         1  
  1         3  
12 1     1   24 use Cwd;
  1         1  
  1         57  
13 1     1   679 use Data::Dumper;
  1         5362  
  1         61  
14 1     1   790 use List::Compare;
  1         16606  
  1         1192  
15              
16             extends 'BioX::Wrapper';
17             #with 'MooseX::Getopt';
18             with 'MooseX::Getopt::Usage';
19             with 'MooseX::Getopt::Usage::Role::Man';
20              
21             =head1 NAME
22              
23             BioX::Wrapper::Gemini - A simple wrapper around the python Gemini library for annotating VCF files.
24              
25             =head1 SYNOPSIS
26              
27             =head2 Basic Usage
28              
29             gemini_wrapper.pl --indir /path/to/vcfs --outdir /location/we/can/write/to > commands.in
30              
31             =head2 Customized workflow
32              
33             For more involved usage please see L<BioX::Wrapper::Gemini::Example>
34              
35             =head2 Using the API
36              
37             BioX::Wrapper::Gemini is written using Moose and can be extended in all the usual fashions.
38              
39             use BioX::Wrapper::Gemini;
40              
41             after 'db_load' =>
42             sub {
43             my $self = shift;
44             # Run some commands
45             # SCIENCE!
46             }
47              
48             =head1 Description
49              
50             A wrapper around Gemini for processing files.
51              
52             Read more about Gemini here: http://gemini.readthedocs.org/en/latest/
53              
54             The workflow described is taken straight from the documentation written by the
55             author of Gemini.
56              
57             For more customization please see the attributes sections of the docs
58              
59             =cut
60              
61             =head2 Attributes
62              
63             Moose Attributes
64              
65             =head2 vcfs
66              
67             VCF files can be given individually as well.
68              
69             #Option is an ArrayRef and can be given as either
70              
71             --vcfs 1.vcf,2.vcf,3.vcfs
72              
73             #or
74              
75             --vcfs 1.vcf --vcfs 2.vcf --vcfs 3.vcf
76              
77             Don't mix the methods
78              
79             If these vcfs are uncompressed, they will be compressed in place. Please make sure either this location has read/write access, or create a symbolic link to someplace
80              
81             Everytime you leave genomics data uncompressed a kitten dies!
82              
83             =cut
84              
85             has 'vcfs' => (
86             is => 'rw',
87             isa => 'ArrayRef',
88             required => 0,
89             documentation => 'List of vcfs if not using --indir option. This --vcfs 1.vcf --vcfs 2.vcf --vcfs 3.vcf or this --vcfs 1.vcf,2.vcf,3.vcfs'
90             );
91              
92             =head2 uncomvcfs
93              
94             Vcfs that are uncompressed
95              
96             =cut
97              
98             has 'uncomvcfs' => (
99             metaclass => 'NoGetopt',
100             is => 'rw',
101             isa => 'ArrayRef',
102             required => 0,
103             default => sub{[]},
104             );
105              
106             =head2 ref
107              
108             Supply a path to a reference genome
109              
110             Default is to assume there is an environmental variable $REFGENOME
111              
112             =cut
113              
114             has 'ref' => (
115             is => 'rw',
116             isa => 'Str',
117             required => 0,
118             default => "\$REFGENOME",
119             documentation => 'Path to reference genome. Assumes it is stored in an environmental variable \$REFGENOME'
120             );
121              
122             =head2 snpeff
123              
124             Base directory of snpeff
125              
126             The default assumes there is an environmental variable of $SNPEFF, being the base directory of the snpeff installation.
127              
128             =cut
129              
130             # TODO
131             # Add documentation for bioinformatics modules using environment modules
132              
133             has 'snpeff' => (
134             is => 'rw',
135             isa => 'Str',
136             required => 0,
137             default => "\$SNPEFF",
138             documentation => 'Base directory of SnpEff. Assumes it is stored in an environmental variable \$SNPEFF'
139             );
140              
141             =head2 snpeff_opt
142              
143             Options to run snpeff with
144              
145             Default is -c \$SNPEFF/snpEff.config -formatEff -classic GRCh37.75
146              
147             =cut
148              
149             has snpeff_opt => (
150             is => 'rw',
151             isa => 'Str',
152             required => 0,
153             default => "-c \$SNPEFF/snpEff.config -formatEff -classic GRCh37.75 ",
154             documentation => "Snpeff run parameters. Default -c \$SNPEFF/snpEff.config -formatEff -classic GRCh37.75",
155             );
156              
157             =head2 ped
158              
159             If all vcf files are being loaded into the gemini db with the same pedigree file, simply change the --db_load_opts to correspond to your file.
160              
161             If each vcf file has its own pedigree, make sure the pedigree file matches the basename of the vcf.
162              
163             Basenames are captured like so:
164              
165             my @gzipbase = map { basename($_, ".vcf.gz") } @gzipped ;
166             my @notgzipbase = map { basename($_, ".vcf") } @notgzipped ;
167              
168             With the extension being .vcf.gz/.vcf
169              
170             Invoke this with --ped
171              
172             Exact specifications should be found here:
173              
174             http://gemini.readthedocs.org/en/latest/content/preprocessing.html#describing-samples-with-a-ped-file
175              
176             =cut
177              
178             has 'ped' => (
179             is => 'rw',
180             isa => 'Bool',
181             required => 0,
182             default => 0,
183             documentation => 'Load gemini with pedigre option. Pedigree should be named in the same convention as the vcf files processed. Family01.vcf Family01.ped'
184             );
185              
186             =head2 ped_dir
187              
188             If using the --ped option you must specify this if your pedigree files are not in the same directory as the --indir option
189              
190             =cut
191              
192             has 'ped_dir' => (
193             is => 'rw',
194             isa => 'Str',
195             required => 0,
196             lazy => 1,
197             default => '',
198             documentation => 'You must specify this directory if your pedigree files are not in the same location as --indir',
199             );
200              
201             =head2 db_load_opts
202              
203             Options for loading VCF file into gemini sqlite db
204              
205             Default is -t snpEff
206              
207             This used to be --skip_cadd -t snpeff, but by popular demand is now just -t snpEff
208              
209             =cut
210              
211             has db_load_opts => (
212             is => 'rw',
213             isa => 'Str',
214             required => 0,
215             default => "-t snpEff"
216             );
217              
218             =head2 Subroutines
219              
220             Subroutines
221              
222             =cut
223              
224             =head2 check_files
225              
226             Check to make sure either an indir or vcfs are supplied
227              
228             =cut
229              
230             sub check_files {
231 0     0     my($self) = @_;
232              
233 0           my($t);
234              
235 0 0 0       die print "Must specificy an indirectory or vcfs!\n" if (!$self->indir && !$self->vcfs);
236              
237 0 0         if($self->indir){
238 0           $t = $self->indir;
239 0           $t =~ s/\/$//g;
240 0           $self->indir($t);
241             }
242              
243 0           $t = $self->outdir;
244 0           $t =~ s/\/$//g;
245 0           $t = $t."/gemini-wrapper";
246 0           $self->outdir($t);
247              
248             #make the outdir
249 0 0         make_path($self->outdir) if ! -d $self->outdir;
250 0 0         make_path($self->outdir."/norm_annot_vcf") if ! -d $self->outdir."/norm_annot_vcf";
251 0 0         make_path($self->outdir."/gemini_sqlite") if ! -d $self->outdir."/gemini_sqlite";
252             }
253              
254             =head2 find_vcfs
255              
256             Use File::Find::Rule to find the vcfs
257              
258             Make sure they are all gzipped first. If there are any .vcf$ files without a corresponding .vcf.gz$, bgzip those
259              
260             =cut
261              
262             sub find_vcfs{
263 0     0     my($self) = @_;
264              
265 0 0         return if $self->vcfs;
266 0           $self->vcfs([]);
267              
268 0           my @gzipped = File::Find::Rule->file->name(qr/(\.vcf\.gz)$/)->in( $self->indir);
269 0           my @notgzipped = File::Find::Rule->file->name(qr/(\.vcf)$/)->in( $self->indir);
270              
271 0           my @gzipbase = map { basename($_, ".vcf.gz") } @gzipped ;
  0            
272 0           my @notgzipbase = map { basename($_, ".vcf") } @notgzipped ;
  0            
273              
274 0           my $lc = List::Compare->new(\@notgzipbase, \@gzipbase);
275              
276 0           my @gzipthese = $lc->get_Lonly;
277              
278 0 0         if(@gzipthese){
279 0           foreach my $i (@gzipthese){
280 0           push(@{$self->uncomvcfs}, $self->indir."/".$i.".vcf");
  0            
281             #push(@{$self->vcfs}, $self->indir."/".$i.".vcf.gz");
282 0           push(@{$self->vcfs}, $i);
  0            
283             }
284             }
285              
286 0           foreach my $i (@gzipbase){
287             #push(@{$self->vcfs}, $self->indir."/".$i.".vcf.gz")
288 0           push(@{$self->vcfs}, $i);
  0            
289             }
290              
291 0           print "\n\n#######################################################################\n";
292 0           print "# Starting Sample Info Section\n";
293 0           print "#######################################################################\n\n";
294              
295 0           print "# ".join(", ", @{$self->vcfs})."\n";
  0            
296              
297 0           print "\n#######################################################################\n";
298 0           print "# Ending Sample Info Section\n";
299 0           print "#######################################################################\n";
300              
301 0           $self->bgzip();
302 0 0         die print "No vcfs were found!\n" unless $self->vcfs;
303             }
304              
305             =head2 bgzip
306              
307             Run bgzip command on files found in find_vcfs
308              
309             =cut
310              
311             sub bgzip{
312 0     0     my($self) = shift;
313              
314 0 0         return unless $self->uncomvcfs;
315              
316 0           print "\n\n#######################################################################\n";
317 0           print "# Starting Bgzip Section\n";
318 0           print "#######################################################################\n";
319 0           print "# The following samples must be bgzipped before processing can begin\n";
320 0           print "# ".join(", ", @{$self->uncomvcfs})."\n";
  0            
321 0           print "#######################################################################\n\n";
322              
323 0           foreach my $i (@{$self->uncomvcfs}){
  0            
324 0           print "bgzip $i && tabix $i.gz\n"
325             }
326              
327 0           print "wait\n";
328 0           print "\n\n#######################################################################\n";
329 0           print "# Finished Bgzip Section\n";
330 0           print "#######################################################################\n\n";
331             }
332              
333             =head2 norml
334              
335             normalize vcfs using vt and annotate using SNPEFF
336              
337             =cut
338              
339             # TODO
340             # Add in option for vep annotation
341              
342             sub norml {
343 0     0     my($self) = shift;
344              
345 0           print "#######################################################################\n";
346 0           print "# Normalizing with VT and annotating with SNPEFF the following samples\n";
347 0           print "# ".join(", ", @{$self->vcfs})."\n";
  0            
348 0           print "#######################################################################\n\n";
349              
350 0           foreach my $vcf (@{$self->vcfs}){
  0            
351              
352 0           my $cmd .=<<EOF;
353             bcftools view $self->{indir}/$vcf.vcf.gz | sed 's/ID=AD,Number=./ID=AD,Number=R/' \\
354             | vt decompose -s - \\
355             | vt normalize -r $self->{ref} - \\
356             | java -Xmx4G -jar $self->{snpeff}/snpEff.jar $self->{snpeff_opt} \\
357             | bgzip -c > \\
358             $self->{outdir}/norm_annot_vcf/$vcf.norm.snpeff.gz && tabix $self->{outdir}/norm_annot_vcf/$vcf.norm.snpeff.gz
359             EOF
360              
361 0           print $cmd."\n\n";
362             }
363              
364 0           print "wait\n";
365 0           print "\n\n#######################################################################\n";
366 0           print "# Finished Normalize Annotate Section\n";
367 0           print "#######################################################################\n\n";
368             }
369              
370              
371             =head2 db_load
372              
373             Load DB into gemini
374              
375             =cut
376              
377             sub db_load {
378 0     0     my($self) = @_;
379              
380 0           print "#######################################################################\n";
381 0           print "# Gemini is loading the following samples\n";
382 0           print "# ".join(", ", @{$self->vcfs})."\n";
  0            
383 0           print "#######################################################################\n\n";
384              
385 0 0         if ($self->ped){
386 0 0         $self->ped_dir($self->indir) unless $self->ped_dir;
387             }
388              
389 0           foreach my $vcf (@{$self->vcfs}){
  0            
390              
391 0           my $cmd =<<EOF;
392             gemini load -v $self->{outdir}/norm_annot_vcf/$vcf.norm.snpeff.gz \\
393             $self->{db_load_opts} \\
394             EOF
395 0 0         if($self->ped){
396 0           $cmd .=<<EOF;
397             -p $self->{ped_dir}/$vcf.ped \\
398             EOF
399             }
400              
401 0           $cmd .=<<EOF;
402             $self->{outdir}/gemini_sqlite/$vcf.vcf.db
403             EOF
404              
405 0           print $cmd."\n\n";
406             }
407              
408 0           print "wait\n";
409 0           print "\n\n#######################################################################\n";
410 0           print "# Finished Gemini Load Section\n";
411 0           print "#######################################################################\n";
412             }
413              
414             =head2 run
415              
416             Subroutine that starts everything off
417              
418             =cut
419              
420             sub run {
421 0     0     my($self) = @_;
422              
423 0           $self->print_opts;
424              
425 0           $self->check_files;
426 0           $self->find_vcfs;
427 0           $self->norml;
428 0           $self->db_load;
429             }
430              
431             __PACKAGE__->meta->make_immutable;
432              
433             1;
434              
435             __END__
436              
437             =encoding utf-8
438              
439              
440             =head1 AUTHOR
441              
442             Jillian Rowe E<lt>jillian.e.rowe@gmail.comE<gt>
443              
444             =head1 ACKNOWLEDGEMENTS
445              
446             This module was originally developed at and for Weill Cornell Medical
447             College in Qatar within ITS Advanced Computing Team. With approval from
448             WCMC-Q, this information was generalized and put on github, for which
449             the authors would like to express their gratitude.
450              
451             =head1 COPYRIGHT
452              
453             Copyright 2015- Weill Cornell Medical College in Qatar
454              
455             =head1 LICENSE
456              
457             This library is free software; you can redistribute it and/or modify
458             it under the same terms as Perl itself.
459              
460             =head1 SEE ALSO
461              
462             =cut