1# BioPerl module for Bio::Tools::Run::tRNAscanSE
2#
3# Please direct questions and support issues to <bioperl-l@bioperl.org>
4#
5# Cared for by Bioperl
6#
7# Copyright Bioperl, Mark Johnson <johnsonm-at-gmail-dot-com>
8#
9# Special thanks to Chris Fields, Sendu Bala
10#
11# You may distribute this module under the same terms as perl itself
12#
13# POD documentation - main docs before the code
14
15=head1 NAME
16
17Bio::Tools::Run::tRNAscanSE - Wrapper for local execution of tRNAscan-SE
18
19=head1 SYNOPSIS
20
21  my $factory = Bio::Tools::Run::tRNAscanSE->new(-program => 'tRNAscan-SE');
22
23  # Pass the factory Bio::Seq objects,
24  # returns a Bio::Tools::tRNAscanSE object
25  my $factory = $factory->run($seq);
26  or
27  my $factory = $factory->run(@seq);
28
29=head1 DESCRIPTION
30
31Wrapper module for tRNAscan-SE.
32
33tRNAscan-SE is open source and available at
34L<http://lowelab.ucsc.edu/software/>.
35
36=head1 FEEDBACK
37
38=head2 Mailing Lists
39
40User feedback is an integral part of the evolution of this and other
41Bioperl modules. Send your comments and suggestions preferably to one
42of the Bioperl mailing lists.  Your participation is much appreciated.
43
44  bioperl-l@bioperl.org                  - General discussion
45  http://bioperl.org/wiki/Mailing_lists  - About the mailing lists
46
47=head2 Support
48
49Please direct usage questions or support issues to the mailing list:
50
51I<bioperl-l@bioperl.org>
52
53rather than to the module maintainer directly. Many experienced and
54reponsive experts will be able look at the problem and quickly
55address it. Please include a thorough description of the problem
56with code and data examples if at all possible.
57
58=head2 Reporting Bugs
59
60Report bugs to the Bioperl bug tracking system to help us keep track
61the bugs and their resolution.  Bug reports can be submitted via the
62web:
63
64  http://redmine.open-bio.org/projects/bioperl/
65
66=head1 AUTHOR - Mark Johnson
67
68 Email: johnsonm-at-gmail-dot-com
69
70=head1 APPENDIX
71
72The rest of the documentation details each of the object
73methods. Internal methods are usually preceded with a _
74
75=cut
76
77package Bio::Tools::Run::tRNAscanSE;
78
79use strict;
80use warnings;
81
82use Bio::SeqIO;
83use Bio::Root::Root;
84use Bio::Tools::Run::WrapperBase;
85use Bio::Tools::tRNAscanSE;
86use English;
87use IPC::Run;     # Should be okay on WIN32 (See IPC::Run Docs)
88
89use base qw(Bio::Root::Root Bio::Tools::Run::WrapperBase);
90
91our @params              = (qw(program));
92our @tRNAscanSE_switches = (qw(A B C G O P));
93
94=head2 program_name
95
96 Title   : program_name
97 Usage   : $factory>program_name()
98 Function: gets/sets the program name
99 Returns:  string
100 Args    : string
101
102=cut
103
104sub program_name {
105
106    my ($self, $val) = @_;
107
108    $self->program($val) if $val;
109
110    return $self->program();
111
112}
113
114=head2 program_dir
115
116 Title   : program_dir
117 Usage   : $factory->program_dir()
118 Function: gets/sets the program dir
119 Returns:  string
120 Args    : string
121
122=cut
123
124sub program_dir {
125
126    my ($self, $val) = @_;
127
128    $self->{'_program_dir'} = $val if $val;
129
130    return $self->{'_program_dir'};
131
132}
133
134=head2 new
135
136 Title   : new
137 Usage   : $tRNAscanSE->new(@params)
138 Function: creates a new tRNAscanSE factory
139 Returns:  Bio::Tools::Run::tRNAscanSE
140 Args    :
141
142=cut
143
144sub new {
145
146       my ($class,@args) = @_;
147       my $self = $class->SUPER::new(@args);
148
149       $self->io->_initialize_io();
150
151       $self->_set_from_args(
152                             \@args,
153                             -methods => [
154                                          @params,
155                                          @tRNAscanSE_switches,
156                                         ],
157                             -create =>  1,
158                         );
159
160       unless (defined($self->program())) {
161           $self->throw('Must specify program');
162       }
163
164       return $self;
165
166}
167
168=head2 run
169
170 Title   :   run
171 Usage   :   $obj->run($seq_file)
172 Function:   Runs tRNAscan-SE
173 Returns :   A Bio::Tools::tRNAscanSE object
174 Args    :   An array of Bio::PrimarySeqI objects
175
176=cut
177
178sub run{
179
180    my ($self, @seq) = @_;
181
182    unless (@seq) {
183        $self->throw("Must supply at least one Bio::PrimarySeqI");
184    }
185
186    foreach my $seq (@seq) {
187
188        unless ($seq->isa('Bio::PrimarySeqI')) {
189            $self->throw("Object does not implement Bio::PrimarySeqI");
190        }
191
192    }
193
194    my $program_name = $self->program_name();
195    my $file_name    = $self->_write_seq_file(@seq);
196
197    return $self->_run($file_name);
198
199}
200
201=head2 _run
202
203 Title   :   _run
204 Usage   :   $obj->_run()
205 Function:   Internal(not to be used directly)
206 Returns :   An instance of Bio::Tools::tRNAscanSE
207 Args    :   file name
208
209=cut
210
211sub _run {
212
213    my ($self, $seq_file_name) = @_;
214
215    my @cmd = (
216               $self->executable(),
217               split(/\s+/, $self->_setparams()),
218               $seq_file_name,
219           );
220
221    my $cmd = join(' ', @cmd);
222    $self->debug("tRNAscan-SE Command = $cmd");
223
224    my $program_name = $self->program_name();
225    my ($program_stderr);
226
227    my ($output_fh, $output_file_name) = $self->io->tempfile(-dir=> $self->tempdir());
228
229
230    my @ipc_args = (\@cmd, \undef, '>', $output_file_name, '2>', \$program_stderr);
231
232    # Run the program via IPC::Run so:
233    # 1) The console doesn't get cluttered up with the program's STDERR/STDOUT
234    # 2) We don't have to embed STDERR/STDOUT redirection in $cmd
235    # 3) We don't have to deal with signal handling (IPC::Run should take care
236    #    of everything automagically.
237
238    eval {
239        IPC::Run::run(@ipc_args) || die $CHILD_ERROR;;
240    };
241
242    if ($EVAL_ERROR) {
243        $self->throw("tRNAscan-SE call crashed: $EVAL_ERROR");
244    }
245
246    $self->debug(join("\n", 'tRNAscanSE STDERR:', $program_stderr)) if $program_stderr;
247
248    return Bio::Tools::tRNAscanSE->new(-file => $output_file_name);
249
250}
251
252sub _setparams {
253
254    my ($self) = @_;
255
256    my $param_string = $self->SUPER::_setparams(
257                                                -params   => [ ],
258                                                -switches => [
259                                                              @tRNAscanSE_switches,
260                                                             ],
261                                                -dash     => 1
262
263                                            );
264
265    # Kill leading and trailing whitespace
266    $param_string =~ s/^\s+//g;
267    $param_string =~ s/\s+$//g;
268
269    return $param_string;
270
271}
272
273=head2 _write_seq_file
274
275 Title   :   _write_seq_file
276 Usage   :   obj->_write_seq_file($seq) or obj->_write_seq_file(@seq)
277 Function:   Internal(not to be used directly)
278 Returns :   Name of a temp file containing program output
279 Args    :   One or more Bio::PrimarySeqI objects
280
281=cut
282
283sub _write_seq_file {
284
285    my ($self, @seq) = @_;
286
287    my ($fh, $file_name) = $self->io->tempfile(-dir=>$self->tempdir());
288    my $out              = Bio::SeqIO->new(-fh => $fh , '-format' => 'Fasta');
289
290    foreach my $seq (@seq){
291	$out->write_seq($seq);
292    }
293
294    close($fh);
295    $out->close();
296
297    return $file_name;
298
299}
300
3011;
302