can download plant phenotype data in the same way as plot phenotype data
[sgn.git] / lib / SGN / Controller / Blast.pm
blob0d94113637bc79dd6aeea5b8f4f8c3b1d7d6c185
2 package SGN::Controller::Blast;
4 use Moose;
6 use POSIX;
7 use Data::Dumper;
8 use Storable qw | nstore retrieve |;
9 use List::Util qw/sum/;
10 use Bio::SeqIO;
11 use CXGN::Tools::Text qw/ sanitize_string /;
12 #use SGN::Schema;
13 use CXGN::Blast::SeqQuery;
16 BEGIN { extends 'Catalyst::Controller'; }
18 sub AUTO {
19 my $self = shift;
20 my $c = shift;
21 SGN::Schema::BlastDb->dbpath($c->config->{blast_db_path});
24 sub index :Path('/tools/blast/') :Args(0) {
25 my $self = shift;
26 my $c = shift;
28 my $db_id = $c->req->param('db_id');
30 my $seq = $c->req->param('seq');
31 my $schema = $c->dbic_schema("SGN::Schema");
33 my $blast_db_icons = $c->config->{blast_db_icons};
34 my $group_rs = $schema->resultset("BlastDbGroup")->search( undef, { order_by=>'ordinal' });
36 my $databases = {};
37 my $dataset_groups = [];
39 my $preselected_database = $c->config->{preselected_blastdb};
40 my $preselected_category = '';
42 # 224 is the database id for tomato cDNA ITAG 2.40 on production
43 # $preselected_database = 224;
45 if ($db_id) {
46 my $rs = $schema->resultset("BlastDb")->search( { blast_db_id => $db_id }, { join => 'blast_db_group' });
48 if ($rs == 0) {
49 $c->throw( is_error => 0, message => "The blast database with id $db_id could not be found.");
52 $preselected_database = $rs->first()->blast_db_id(); # first database of the category
53 $preselected_category = $rs->first()->blast_db_group_id();
56 foreach my $g ($group_rs->all()) {
57 my @blast_dbs = $g->blast_dbs();
58 push @$dataset_groups, [ $g->blast_db_group_id, $g->name() ];
60 my @dbs_AoA;
62 foreach my $db (@blast_dbs) {
63 push @dbs_AoA, [ $db->blast_db_id(), $db->title(), $db->type() ];
66 my @arr = sort {$a->[1] cmp $b->[1]} @dbs_AoA;
67 $databases->{ $g->blast_db_group_id } = \@arr;
70 my $cbsq = CXGN::Blast::SeqQuery->new();
71 my @input_options = sort {$a->[0] cmp $b->[0]} ( map { [ $_->name(), $_->name(), $_->type(), $_->example() ] } $cbsq->plugins() );
73 my $cbp = CXGN::Blast::Parse->new();
74 my @parse_options = sort { $b->[0] cmp $a->[0] } ( map { [ $_->name(), $_->name() ] } $cbp->plugins() );
76 # # remove the Basic option from the list (it will still be the default if nothing is selected)
77 # #
78 # for (my $i=0; $i<@parse_options; $i++) {
79 # if ($parse_options[$i]->[0] eq 'Basic') {
80 # delete($parse_options[$i]);
81 # }
82 # }
84 #print STDERR "INPUT OPTIONS: ".Data::Dumper::Dumper(\@input_options);
85 #print STDERR "GROUPS: ".Data::Dumper::Dumper($dataset_groups);
86 #print STDERR "DATASETS: ".Data::Dumper::Dumper($databases);
88 # print STDERR "controller pre-selected db: $preselected_database\n";
90 $c->stash->{input_options} = \@input_options;
91 $c->stash->{parse_options} = \@parse_options;
92 $c->stash->{preselected_database} = $preselected_database;
93 $c->stash->{preselected_category} = $preselected_category;
94 $c->stash->{seq} = $seq;
95 $c->stash->{preload_id} = $c->req->param('preload_id');
96 $c->stash->{preload_type} = $c->req->param('preload_type');
98 $c->stash->{blast_db_icons} = $blast_db_icons;
100 $c->stash->{databases} = $databases;
101 $c->stash->{dataset_groups} = $dataset_groups;
102 $c->stash->{preload_seq} = $seq;
103 $c->stash->{programs} = [
104 [ 'blastn', 'blastn (nucleotide to nucleotide db)' ],
105 [ 'blastp', 'blastp (protein to protein db)' ],
106 [ 'blastx', 'blastx (translated nucleotide to protein db)'],
107 [ 'tblastn', 'tblastn (protein to translated nucleotide db)'],
108 [ 'tblastx', 'tblastx (translated nucleotide to translated nucleotide db)'],
110 $c->stash->{template} = '/tools/blast/index.mas';
113 sub dbinfo : Path('/tools/blast/dbinfo') Args(0) {
114 my $self = shift;
115 my $c = shift;
117 my $data = [];
119 my $schema = $c->dbic_schema("SGN::Schema");
122 my $cache = $c->config->{basepath}."/".$c->tempfiles_subdir("blast")."/dbinfo_cache";
123 if ((-e $cache) && ($c->req->param("force") != 1)) {
124 $data = retrieve($cache);
126 else {
127 my $group_rs = $schema->resultset('BlastDbGroup')->search({}, { order_by => 'ordinal, name' });
128 while (my $group_row = $group_rs->next()) {
129 my $db_rs = $group_row->blast_dbs->search({ web_interface_visible => 't'});
130 my @groups = ();
131 while (my $db_row = $db_rs->next()) {
132 if ($db_row->files_exist()) {
134 push @groups, {
135 title => $db_row->title(),
136 sequence_type => $db_row->type(),
137 sequence_count => $db_row->sequences_count(),
138 update_freq => $db_row->update_freq(),
139 description => $db_row->description(),
140 source_url => $db_row->source_url(),
141 current_as_of => strftime('%m-%d-%y %R GMT',gmtime $db_row->file_modtime),
142 needs_update => $db_row->needs_update(),
146 push @$data, [ $group_row->blast_db_group_id(), $group_row->name(), \@groups ];
149 my $ungrouped_rs = $schema->resultset('BlastDb')->search(
150 { blast_db_group_id => undef,
151 web_interface_visible => 't' },
152 {order_by => 'title'}
155 my @other_groups = ();
156 if ($ungrouped_rs) {
157 while (my $db_row = $ungrouped_rs->next()) {
158 if ($db_row->files_exist()) {
159 push @other_groups, {
160 title => $db_row->title(),
161 sequence_type => $db_row->type(),
162 sequence_count => $db_row->sequences_count(),
163 update_freq => $db_row->update_freq(),
164 description => $db_row->description(),
165 source_url => $db_row->source_url(),
166 current_as_of => strftime('%m-%d-%y %R GMT',gmtime $db_row->file_modtime),
167 needs_update => $db_row->needs_update(),
171 push @$data, [ 0, 'Other', \@other_groups ];
173 nstore($data, $cache);
176 $c->stash->{template} = '/tools/blast/dbinfo.mas';
177 $c->stash->{groups} = $data;
180 sub show_match_seq : Path('/tools/blast/match/show') Args(0) {
181 my $self = shift;
182 my $c = shift;
183 my $id = $c->req->param('id');
184 my $blast_db_id = $c->req->param('blast_db_id');
185 my $format = $c->req->param('format');
186 my $hilite_coords = $c->req->param('hilite_coords');
188 $format ||= 'html';
189 $blast_db_id += 0;
190 $id = sanitize_string( $id );
192 $c->stash->{template} = '/blast/show_seq/input.mas' unless $blast_db_id && defined $id;
194 # look up our blastdb
195 my $schema = $c->dbic_schema("SGN::Schema");
196 my $bdbo = $schema->resultset("BlastDb")->find($blast_db_id)
197 or $c->throw( is_error => 0,
198 message => "The blast database with id $blast_db_id could not be found (please set the blast_db_id parameter).");
199 my $seq = $bdbo->get_sequence($id) # returns a Bio::Seq object.
200 or $c->throw( is_error => 0,
201 message => "The sequence could not be found in the blast database with id $blast_db_id.");
203 # parse the coords param
204 my @coords =
205 map {
206 my ($s, $e) = split "-", $_;
207 defined $_ or die 'parse error' for $s, $e;
208 [ $s, $e ]
210 grep length,
211 split ',', ( $hilite_coords || '' );
213 # dispatch to the proper view
214 if ($format eq 'html') {
216 my $view_link = '';
217 my $download_link = ''; #do { $format => 'fasta_file'; '?'.$c->req->body };
219 $c->stash->{template} = '/blast/show_seq/html.mas';
220 $c->stash->{seq} = $seq;
221 $c->stash->{highlight_coords} = \@coords;
222 $c->stash->{source} = '"'.$bdbo->title().'" BLAST dataset ';
223 $c->stash->{format_links} = [
224 ( $seq->length > 500_000 ? () : [ 'View as FASTA' => $view_link ] ),
225 [ 'Download as FASTA' => $download_link ],
227 $c->stash->{blast_url} = '/tools/blast';
230 elsif($format eq 'fasta_file' || $format eq 'fasta_text') {
233 my $attachment = $format eq 'fasta_file' ? 'attachment;' : '';
234 $c->res->body(qq | Content-Type: text/plain\n\n | .
236 "Content-Disposition: $attachment filename=$id.fa\n\n".
237 Bio::SeqIO->new( -fh => \*STDOUT, -format => 'fasta' )
238 ->write_seq( $seq ));
242 sub blast_help :Path('/help/tools/blast') :Args(0) {
243 my $self = shift;
244 my $c = shift;
246 $c->stash->{template} = '/help/blast.mas';