1 package SGN
::Controller
::Search
::Feature
;
3 use namespace
::autoclean
;
5 use SGN
::View
::Feature
qw( location_string description_featureprop_types get_descriptions feature_types feature_organisms);
7 use URI
::FromHash
'uri';
11 BEGIN { extends
'Catalyst::Controller' }
12 with
'Catalyst::Component::ApplicationAttribute';
14 has
'default_page_size' => (
19 has
'maximum_export_size' => (
26 isa
=> 'DBIx::Class::Schema',
30 shift->_app->dbic_schema( 'Bio::Chado::Schema', 'sgn_chado' )
37 Interactive search interface for features.
39 Public path: /search/features
43 sub oldsearch
: Path
('/feature/search') Args
(0) {
44 $_[1]->res->redirect( '/search/features', 301 );
47 sub search
:Path
('/search/features') Args
(0) {
48 my ( $self, $c ) = @_;
51 template
=> '/search/features.mas',
52 maximum_export_size
=> $self->maximum_export_size,
53 feature_types
=> feature_types
($self->schema),
54 organisms
=> feature_organisms
($self->schema) ,
56 $c->forward('View::Mason');
59 sub csv_export_search
: Path
('/search/features/export_csv') {
60 my ( $self, $c ) = @_;
62 $c->forward('format_search_args');
63 $c->forward('make_feature_search_rs');
65 if( $c->stash->{search_resultset
}->count > $self->maximum_export_size ) {
66 $c->throw_client_error( public_message
=> <<'' );
67 The search matched too many records
, please make your search more specific
.
71 $c->forward('assemble_result');
73 my @headings = @
{ $c->stash->{search_result_fields
} || [] };
74 my $results = $c->stash->{search_result
};
75 my $body = join( ',', map '"'.ucfirst($_).'"', @headings )."\n";
76 for my $r ( @
$results ) {
77 no warnings
'uninitialized';
84 $c->res->content_type( 'text/csv' );
85 $c->stash->{download_filename
} = 'SGN_features.csv';
86 $c->forward('/download/set_download_headers');
87 $c->res->body( $body );
90 sub format_search_args
: Private
{
91 my ( $self, $c ) = @_;
93 my $params = $c->req->params;
94 $c->stash->{search_args
} = {
116 sub search_json
:Path
('/search/features/search_service') Args
(0) {
117 my ( $self, $c ) = @_;
119 $c->forward('format_search_args');
120 $c->forward('make_feature_search_rs');
122 my $rs = $c->stash->{search_resultset
};
124 my $params = $c->req->params;
125 my $total = $rs->count;
127 # set up paging if specified
128 if( defined $params->{'page'} ) {
129 $rs = $c->stash->{search_resultset
} = $rs->search(
132 page
=> $params->{'page'} || 1,
133 rows
=> $params->{'limit'} || $self->default_page_size,
138 $c->forward('assemble_result');
140 $c->res->body( to_json
( {
141 success
=> JSON
::true
,
142 totalCount
=> $total,
143 data
=> $c->stash->{search_result
},
147 sub assemble_result
: Private
{
148 my ( $self, $c ) = @_;
150 my $rs = $c->stash->{search_resultset
};
152 # make sure we prefetch some stuff
153 $rs = $rs->search( undef,
158 ( $rs->is_paged ?
() : ( { 'featureloc_features' => 'srcfeature' } ) ),
164 my $fields = $c->stash->{search_result_fields
} = $c->req->params->{fields
} || [qw
[
174 my %field_handlers = (
175 organism
=> sub { shift->organism->species },
176 type
=> sub { shift->type->name },
177 name
=> sub { shift->name },
178 feature_id
=> sub { shift->feature_id },
179 seqlen
=> sub { shift->seqlen },
183 location_string
( $fl );
184 } shift->featureloc_features
187 description
=> sub { join ' ', get_descriptions
( shift, 'no_html' ) },
191 while( my $feature = $rs->next ) {
193 map { $_ => $field_handlers{ $_ }->( $feature ) }
194 grep $field_handlers{$_}, # only try to make the fields we know how to make
195 @
{ ref $fields ?
$fields : [$fields] }
199 $c->stash->{search_result
} = \
@result;
202 sub feature_type_autocomplete
: Path
('/search/features/feature_types_service') {
203 my ( $self, $c ) = @_;
204 $c->stash->{typed_table
} = 'feature';
205 $c->forward( 'type_autocomplete' );
208 sub featureprop_type_autocomplete
: Path
('/search/features/featureprop_types_service') {
209 my ( $self, $c ) = @_;
210 $c->stash->{typed_table
} = 'featureprop';
211 $c->forward( 'type_autocomplete' );
214 sub type_autocomplete
: Private
{
215 my ( $self, $c ) = @_;
217 my $table = $c->stash->{typed_table
} || 'feature';
218 my $types = $c->dbc->dbh->selectall_arrayref(<<"" );
219 SELECT cvterm_id
, name
221 WHERE cvterm_id IN
( SELECT DISTINCT type_id FROM
$table )
224 $c->res->content_type('text/json');
225 $c->res->body( to_json
( { success
=> JSON
::true
,
227 map +{ type_id
=> $_->[0], name
=> $_->[1] }, @
{ $types || [] }
234 sub srcfeatures_autocomplete
: Path
('/search/features/srcfeatures_service') {
235 my ( $self, $c ) = @_;
237 my $srcfeatures = $c->dbc->dbh->selectall_arrayref(<<'' );
238 SELECT srcfeature_id
, f
.name
, f
.seqlen
, count
240 ( SELECT srcfeature_id
, count
(*) as count
242 GROUP BY srcfeature_id
245 JOIN feature f ON srcfeature_id
= f
.feature_id
249 $c->res->content_type('text/json');
250 $c->res->body( to_json
( { success
=> JSON
::true
,
252 map +{ feature_id
=> $_->[0], name
=> $_->[1], seqlen
=> $_->[2], count
=> $_->[3] }, @
{ $srcfeatures || [] }
259 # assembles a DBIC resultset for the search based on the submitted
261 sub make_feature_search_rs
: Private
{
262 my ( $self, $c ) = @_;
264 my $args = $c->stash->{search_args
};
266 my $schema = $c->dbic_schema('Bio::Chado::Schema','sgn_chado');
267 #my $rs = $schema->resultset('Sequence::Feature');
268 #Get only features that have locations in featureloc
269 my $rs = $schema->resultset('Sequence::Feature')->search(
270 {'featureloc_features.locgroup' => 0},
271 {prefetch
=> ['featureloc_features']}
275 #$schema->storage->debug(1);
277 if( my $name = $args->{'name'} ) {
278 $rs = $rs->search({ 'me.name' => { ilike
=> '%'.$name.'%' }});
281 if( my $type = $args->{'type'} ) {
282 my $type_rs = $schema->resultset('Cv::Cvterm')
283 ->search({ 'lower(name)' => lc $type });
284 $rs = $rs->search({ 'me.type_id' => { -in => $type_rs->get_column('cvterm_id')->as_query }});
287 if( my $type_id = $args->{'type_id'} ) {
288 $rs = $rs->search({ 'me.type_id' => $type_id });
291 if( my $organism = $args->{'organism'} ) {
292 my $organism_rs = $schema->resultset('Organism::Organism')
293 ->search({ species
=> { -ilike
=> '%'.$organism.'%' }});
294 $rs = $rs->search({ 'me.organism_id' => { -in => $organism_rs->get_column('organism_id')->as_query } });
297 my $featureloc_prefetch = { prefetch
=> { 'featureloc_features' => 'srcfeature' }};
298 if( my $srcfeature_id = $args->{'srcfeature_id'} ) {
299 $rs = $rs->search({ 'featureloc_features.srcfeature_id' => $srcfeature_id }, $featureloc_prefetch );
302 if( my $start = $args->{'srcfeature_start'} ) {
303 $rs = $rs->search({ 'featureloc_features.fmax' => { '>=' => $start } }, $featureloc_prefetch );
306 if( my $end = $args->{'srcfeature_end'} ) {
307 $rs = $rs->search({ 'featureloc_features.fmin' => { '<=' => $end+1 } }, $featureloc_prefetch );
310 if( my $proptype_id = $args->{'proptype_id'} ) {
311 $rs = $rs->search({ 'featureprops.type_id' => $proptype_id },{ prefetch
=> 'featureprops' });
314 if( my $prop_value = $args->{'prop_value'} ) {
315 $rs = $rs->search({ 'featureprops.value' => { -ilike
=> '%'.$prop_value.'%' }},{ prefetch
=> 'featureprops' });
318 if( my $desc = $args->{'description'} ) {
320 'featureprops.value' => { -ilike
=> '%'.$desc.'%' },
321 'featureprops.type_id' => { -in => [description_featureprop_types
( $rs )->get_column('cvterm_id')->all] },
323 prefetch
=> 'featureprops'
329 $rs = $c->stash->{search_resultset
} = $rs->search(
333 '-'.(lc $args->{dir
} || 'asc' )
336 'type' => 'type.name',
337 'organism' => 'organism.species',
339 }->{lc $args->{'sort'}}
346 $c->stash->{search_resultset
} = $rs;