Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

API: updated error messages, added more CV checking #309

Merged
merged 2 commits into from

2 participants

@teharrison
Owner

No description provided.

@jaredbischof jaredbischof merged commit d2abb45 into MG-RAST:develop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 9, 2013
  1. API: updated error messages, added more CV checking

    Travis Harrison authored
This page is out of date. Refresh to see the latest.
View
200 src/MGRAST/lib/resources2/annotation.pm
@@ -0,0 +1,200 @@
+package resources2::annotation;
+
+use strict;
+use warnings;
+no warnings('once');
+
+use Conf;
+use parent qw(resources2::resource);
+
+# Override parent constructor
+sub new {
+ my ($class, @args) = @_;
+
+ # Call the constructor of the parent class
+ my $self = $class->SUPER::new(@args);
+
+ # Add name / attributes
+ $self->{name} = "annotation";
+ $self->{types} = { "organism" => 1, "function" => 1, "ontology" => 1 };
+ $self->{attributes} = { ann => { "id" => [ 'string', 'unique object identifier' ],
+ "data" => [ 'hash', [ { 'key' => ['string', 'annotation text'],
+ 'value' => ['list', ['tuple', 'read id and read sequence']] },
+ 'data type pointing at lists of sequence info' ]],
+ "version" => [ 'integer', 'version of the object' ],
+ "url" => [ 'uri', 'resource location of this object instance' ]},
+ md5 => { "id" => [ 'string', 'unique object identifier' ],
+ "data" => [ 'hash', [ { 'key' => ['string', 'md5sum'],
+ 'value' => ['list', ['tuple', 'read id and read sequence']] },
+ 'annotation to md5s' ]],
+ "version" => [ 'integer', 'version of the object' ],
+ "url" => [ 'uri', 'resource location of this object instance' ]}
+ };
+ return $self;
+}
+
+# resource is called without any parameters
+# this method must return a description of the resource
+sub info {
+ my ($self) = @_;
+ my $content = { 'name' => $self->name,
+ 'url' => $self->cgi->url."/".$self->name,
+ 'description' => "A set of genomic sequences of a metagenome annotated by a specified source",
+ 'type' => 'object',
+ 'documentation' => $self->cgi->url.'/api.html#'.$self->name,
+ 'requests' => [ { 'name' => "info",
+ 'request' => $self->cgi->url."/".$self->name,
+ 'description' => "Returns description of parameters and attributes.",
+ 'method' => "GET" ,
+ 'type' => "synchronous" ,
+ 'attributes' => "self",
+ 'parameters' => { 'options' => {},
+ 'required' => {},
+ 'body' => {} } },
+ { 'name' => "md5",
+ 'request' => $self->cgi->url."/".$self->name."/{ID}",
+ 'description' => "Returns a single data object.",
+ 'method' => "GET" ,
+ 'type' => "synchronous" ,
+ 'attributes' => $self->{attributes}{md5},
+ 'parameters' => { 'options' => { "sequence" => [ "cv", [ [ "dna", "return DNA sequences" ],
+ [ "protein", "return protein sequences" ] ] ],
+ "md5" => [ "list", [ "string", "md5 identifier" ] ] },
+ 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
+ 'body' => {} } },
+ { 'name' => "annotation",
+ 'request' => $self->cgi->url."/".$self->name."/{ID}",
+ 'description' => "Returns a single data object.",
+ 'method' => "GET" ,
+ 'type' => "synchronous" ,
+ 'attributes' => $self->{attributes}{ann},
+ 'parameters' => { 'options' => {
+ "type" => [ "cv", [ [ "organism", "return organism data" ],
+ [ "function", "return function data" ],
+ [ "ontology", "return ontology data" ] ] ],
+ "sequence" => [ "cv", [ [ "dna", "return DNA sequences" ],
+ [ "protein", "return protein sequences" ],
+ [ "md5", "return md5sum" ] ] ],
+ "annotation" => [ "list", [ "string", "data_type to filter by" ] ],
+ "source" => [ "cv", [[ "RefSeq", "protein database, type organism and function only" ],
+ [ "GenBank", "protein database, type organism and function only" ],
+ [ "IMG", "protein database, type organism and function only" ],
+ [ "SEED", "protein database, type organism and function only" ],
+ [ "TrEMBL", "protein database, type organism and function only" ],
+ [ "SwissProt", "protein database, type organism and function only" ],
+ [ "PATRIC", "protein database, type organism and function only" ],
+ [ "KEGG", "protein database, type organism and function only" ],
+ [ "RDP", "RNA database, type organism and function only" ],
+ [ "Greengenes", "RNA database, type organism and function only" ],
+ [ "LSU", "RNA database, type organism and function only" ],
+ [ "SSU", "RNA database, type organism and function only" ],
+ [ "Subsystems", "ontology database, type ontology only" ],
+ [ "NOG", "ontology database, type ontology only" ],
+ [ "COG", "ontology database, type ontology only" ],
+ [ "KO", "ontology database, type ontology only" ]] ] },
+ 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
+ 'body' => {} } }
+ ]
+ };
+
+ $self->return_data($content);
+}
+
+# the resource is called with an id parameter
+sub instance {
+ my ($self) = @_;
+
+ # check id format
+ my $rest = $self->rest;
+ my (undef, $id) = $rest->[0] =~ /^(mgm)?(\d+\.\d+)$/;
+ if ((! $id) && scalar(@$rest)) {
+ $self->return_data( {"ERROR" => "invalid id format: " . $rest->[0]}, 400 );
+ }
+
+ # get database
+ my $master = $self->connect_to_datasource();
+
+ # get data
+ my $job = $master->Job->get_objects( {metagenome_id => $id, viewable => 1} );
+ unless ($job && scalar(@$job)) {
+ $self->return_data( {"ERROR" => "id $id does not exists"}, 404 );
+ } else {
+ $job = $job->[0];
+ }
+
+ # check rights
+ unless ($job->{public} || ($self->user && ($self->user->has_right(undef, 'view', 'metagenome', $job->{metagenome_id}) || $self->user->has_star_right('view', 'metagenome')))) {
+ $self->return_data( {"ERROR" => "insufficient permissions to view this data"}, 401 );
+ }
+
+ # prepare data
+ my $data = $self->prepare_data($job);
+
+ $self->return_data($data);
+}
+
+# reformat the data into the requested output format
+sub prepare_data {
+ my ($self, $data) = @_;
+
+ my $cgi = $self->cgi;
+ my $type = $cgi->param('type') ? $cgi->param('type') : 'organism';
+ my $seq = $cgi->param('sequence') ? $cgi->param('sequence') : 'dna';
+ my $src = $cgi->param('source') ? $cgi->param('source') : 'RefSeq';
+ my @anns = $cgi->param('annotation') ? $cgi->param('annotation') : ();
+ my @md5s = $cgi->param('md5') ? $cgi->param('md5') : ();
+
+ my $master = $self->connect_to_datasource();
+ use MGRAST::Analysis;
+ my $mgdb = MGRAST::Analysis->new( $master->db_handle );
+ unless (ref($mgdb)) {
+ $self->return_data( {"ERROR" => "resource database offline"}, 503 );
+ }
+ unless (exists $mgdb->_src_id->{$src}) {
+ $self->return_data({"ERROR" => "Invalid source was entered ($src). Please use one of: ".join(", ", keys %{$mgdb->_src_id})}, 404);
+ }
+ unless (exists $self->{types}{$type}) {
+ $self->return_data({"ERROR" => "Invalid type was entered ($type). Please use one of: ".join(", ", keys %{$self->{types}})}, 404);
+ }
+
+ my $url = $cgi->url."/".$self->{name}."/mgm".$data->{metagenome_id}."?sequence=".$seq;
+ my $content;
+ if (scalar(@md5s) > 0) {
+ my $md5_ints_to_strings = $mgdb->_get_annotation_map('md5', \@md5s);
+ if (scalar(keys %$md5_ints_to_strings) > 0) {
+ $content = $mgdb->sequences_for_md5s($data->{metagenome_id}, $seq, [keys %$md5_ints_to_strings], 1);
+ my %valid_md5s = map { $_ => 1} values %$md5_ints_to_strings; # uniquifying valid md5s
+ $url .= "&md5=".join("&md5=", keys %valid_md5s);
+ } else {
+ $self->return_data( {"ERROR" => "No valid md5 was entered. For more information on how to use this resource, view the resource description here: ".$cgi->url."/sequences"}, 404 );
+ }
+ } elsif (scalar(@anns) > 0) {
+ if ($seq eq 'md5') {
+ $content = $mgdb->md5_abundance_for_annotations($data->{metagenome_id}, $type, [$src], \@anns); # annotation_text => md5_integer => abundance
+ my $md5_ints = {};
+ foreach my $a (keys %$content) {
+ map { $md5_ints->{$_} = 1 } keys %{$content->{$a}};
+ }
+ my $md5_ints_to_strings = $mgdb->decode_annotation('md5', [keys %$md5_ints]);
+ foreach my $a (keys %$content) {
+ my @md5s = map { $md5_ints_to_strings->{$_} } grep { $md5_ints_to_strings->{$_} } keys %{$content->{$a}};
+ $content->{$a} = \@md5s;
+ }
+ } else {
+ $content = $mgdb->sequences_for_annotation($data->{metagenome_id}, $seq, $type, [$src], \@anns);
+ }
+ $url .= "&source=".$src."&type=".$type."&annotation=".join("&annotation=", @anns);
+ } else {
+ $self->return_data( {"ERROR" => "To retrieve sequences, you must either enter an 'md5' or a 'type' and an 'annotation'. The default 'type' is organism. For more information on how to use this resource, view the resource description here: ".$cgi->url."/sequences"}, 404 );
+ }
+
+ my $object = { id => "mgm".$data->{metagenome_id},
+ data => $content,
+ url => $url,
+ version => 1
+ };
+
+ return $object;
+}
+
+1;
View
190 src/MGRAST/lib/resources2/annotations.pm
@@ -1,190 +0,0 @@
-package resources2::annotations;
-
-use strict;
-use warnings;
-no warnings('once');
-use Data::Dumper;
-
-use Conf;
-use parent qw(resources2::resource);
-
-# Override parent constructor
-sub new {
- my ($class, @args) = @_;
-
- # Call the constructor of the parent class
- my $self = $class->SUPER::new(@args);
-
- # Add name / attributes
- $self->{name} = "annotations";
- $self->{attributes} = { "id" => [ 'string', 'unique object identifier' ],
- "data" => [ 'hash', [ { 'key' => ['string', 'annotation text'],
- 'value' => ['list', ['string', 'md5sum of hit protein']] },
- 'annotation to md5s' ]],
- "version" => [ 'integer', 'version of the object' ],
- "url" => [ 'uri', 'resource location of this object instance' ] };
- return $self;
-}
-
-# resource is called without any parameters
-# this method must return a description of the resource
-sub info {
- my ($self) = @_;
- my $content = { 'name' => $self->name,
- 'url' => $self->cgi->url."/".$self->name,
- 'description' => "All annotations of a metagenome for a specific annotation type and source",
- 'type' => 'object',
- 'documentation' => $self->cgi->url.'/api.html#'.$self->name,
- 'requests' => [
- { 'name' => "info",
- 'request' => $self->cgi->url."/".$self->name,
- 'description' => "Returns description of parameters and attributes.",
- 'method' => "GET" ,
- 'type' => "synchronous" ,
- 'attributes' => "self",
- 'parameters' => { 'required' => {},
- 'options' => {},
- 'body' => {} } },
- { 'name' => "instance",
- 'request' => $self->cgi->url."/".$self->name."/{ID}",
- 'description' => "Returns a single data object.",
- 'method' => "GET" ,
- 'type' => "synchronous" ,
- 'attributes' => $self->{attributes},
- 'parameters' => { 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
- 'options' => { "type" => [ "cv", [[ "organism", "return organism data" ],
- [ "function", "return function data" ],
- [ "ontology", "return ontology data" ]] ],
- "source" => [ "cv", [[ "RefSeq", "protein database, type organism and function only" ],
- [ "GenBank", "protein database, type organism and function only" ],
- [ "IMG", "protein database, type organism and function only" ],
- [ "SEED", "protein database, type organism and function only" ],
- [ "TrEMBL", "protein database, type organism and function only" ],
- [ "SwissProt", "protein database, type organism and function only" ],
- [ "PATRIC", "protein database, type organism and function only" ],
- [ "KEGG", "protein database, type organism and function only" ],
- [ "RDP", "RNA database, type organism and function only" ],
- [ "Greengenes", "RNA database, type organism and function only" ],
- [ "LSU", "RNA database, type organism and function only" ],
- [ "SSU", "RNA database, type organism and function only" ],
- [ "Subsystems", "ontology database, type ontology only" ],
- [ "NOG", "ontology database, type ontology only" ],
- [ "COG", "ontology database, type ontology only" ],
- [ "KO", "ontology database, type ontology only" ]] ],
- 'asynchronous' => [ 'boolean', "if true, return process id to query status resource for results. default is false." ] },
- 'body' => {} } }
- ]
- };
-
- $self->return_data($content);
-}
-
-# the resource is called with an id parameter
-sub instance {
- my ($self) = @_;
-
- # check id format
- my $rest = $self->rest;
- my (undef, $id) = $rest->[0] =~ /^(mgm)?(\d+\.\d+)$/;
- if ((! $id) && scalar(@$rest)) {
- $self->return_data( {"ERROR" => "invalid id format: " . $rest->[0]}, 400 );
- }
-
- # get database
- my $master = $self->connect_to_datasource();
-
- # get data
- my $job = $master->Job->get_objects( {metagenome_id => $id, viewable => 1} );
- unless ($job && scalar(@$job)) {
- $self->return_data( {"ERROR" => "id $id does not exists"}, 404 );
- } else {
- $job = $job->[0];
- }
-
- # check rights
- unless ($job->{public} || ($self->user && ($self->user->has_right(undef, 'view', 'metagenome', $job->{metagenome_id}) || $self->user->has_star_right('view', 'metagenome')))) {
- $self->return_data( {"ERROR" => "insufficient permissions to view this data"}, 401 );
- }
-
- # return cached if exists
- $self->return_cached();
-
- # if asynchronous call, fork the process and return the process id. otherwise, prepare and return data.
- if($self->cgi->param('asynchronous')) {
- my $pid = fork();
- # child - get data and dump it
- if ($pid == 0) {
- my $fname = $Conf::temp.'/'.$$.'.json';
- close STDERR;
- close STDOUT;
- my $data = $self->prepare_data($job);
- open(FILE, ">$fname");
- print FILE $self->json->encode($data);
- close FILE;
- exit 0;
- }
- # parent - end html session
- else {
- my $fname = $Conf::temp.'/'.$pid.'.json';
- $self->return_data({"status" => "Submitted", "id" => $pid, "url" => $self->cgi->url."/status/".$pid});
- }
- } else {
- # prepare data
- my $data = $self->prepare_data($job);
- $self->return_data($data, undef, 1); # cache this!
- }
-}
-
-# reformat the data into the requested output format
-sub prepare_data {
- my ($self, $data) = @_;
-
- my $cgi = $self->cgi;
- my $type = $cgi->param('type') ? $cgi->param('type') : 'organism';
- my $source = $cgi->param('source') ? $cgi->param('source') : (($type eq 'ontology') ? 'Subsystems' : 'RefSeq');
-
- my $master = $self->connect_to_datasource();
- use MGRAST::Analysis;
- my $mgdb = MGRAST::Analysis->new( $master->db_handle );
- unless (ref($mgdb)) {
- $self->return_data( {"ERROR" => "resource database offline"}, 503 );
- }
- my $mgid = $data->{metagenome_id};
- $mgdb->set_jobs([$mgid]);
-
- my $content;
- if ($type eq 'organism') {
- $content = $mgdb->get_org_md5(undef, undef, undef, [$source]);
- } elsif ($type eq 'function') {
- $content = $mgdb->get_func_md5(undef, undef, undef, [$source]);
- } elsif ($type eq 'ontology') {
- $content = $mgdb->get_ontol_md5(undef, undef, undef, $source);
- } else {
- $self->return_data( {"ERROR" => "Invalid annotation type was entered ($type). Please use one of: organism, function, ontology"}, 404 );
- }
-
- my $annotations = {};
- if ($content && exists($content->{$mgid})) {
- my %md5s = ();
- foreach my $ann (keys %{$content->{$mgid}}) {
- map { $md5s{$_} = 1 } keys %{$content->{$mgid}{$ann}};
- }
- my $md5_map = $mgdb->decode_annotation('md5', [keys %md5s]);
- foreach my $ann (keys %{$content->{$mgid}}) {
- my @md5sums = map { $md5_map->{$_} } grep { exists $md5_map->{$_} } keys %{$content->{$mgid}{$ann}};
- if (@md5sums > 0) {
- $annotations->{$ann} = \@md5sums;
- }
- }
- }
-
- my $object = { id => "mgm".$mgid,
- data => $annotations,
- url => $cgi->url."/mgm".$mgid."?type=".$type.'&source='.$source,
- version => 1
- };
-
- return $object;
-}
-
-1;
View
19 src/MGRAST/lib/resources2/m5nr.pm
@@ -17,6 +17,10 @@ sub new {
# Add name / attributes
$self->{name} = "m5nr";
+ $self->{sources} = [ ['Subsystems', 'returns 4 level SEED-Subsystems ontology' ],
+ ['COG', 'returns 3 level COG ontology'],
+ ['NOG', 'returns 3 level NOG ontology'],
+ ['KO', 'returns 4 level KEGG-KO ontology' ] ];
$self->{hierarchy} = { taxonomy => [ ['species', 'taxonomy level'],
['genus', 'taxonomy level'],
['family', 'taxonomy level'],
@@ -69,10 +73,7 @@ sub info {
'method' => "GET",
'type' => "synchronous",
'attributes' => $self->{attributes}{ontology},
- 'parameters' => { 'options' => { 'source' => ['cv', [ ['Subsystems', 'returns 4 level SEED-Subsystems ontology' ],
- ['COG', 'returns 3 level COG ontology'],
- ['NOG', 'returns 3 level NOG ontology'],
- ['KO', 'returns 4 level KEGG-KO ontology' ] ] ],
+ 'parameters' => { 'options' => { 'source' => ['cv', $self->{sources} ],
'id_map' => ['boolean', 'if true overrides other options and returns a map { ontology ID: [ontology levels] }'],
'min_level' => ['cv', $self->{hierarchy}{ontology}],
'parent_name' => ['string', 'name of ontology group to retrieve children of']
@@ -137,15 +138,19 @@ sub static {
if ($type eq 'ontology') {
my @ont_hier = map { $_->[0] } @{$self->{hierarchy}{ontology}};
+ my @src_map = map { $_->[0] } @{$self->{sources}};
my $source = $self->cgi->param('source') || 'Subsystems';
my $min_lvl = $self->cgi->param('min_level') || 'function';
$url .= '?source='.$source.'&min_level='.$min_lvl;
+ unless ( grep(/^$source$/, @src_map) ) {
+ $self->return_data({"ERROR" => "Invalid source was entered ($source). Please use one of: ".join(", ", @src_map)}, 404);
+ }
if ( grep(/^$min_lvl$/, @ont_hier) ) {
if ($min_lvl eq 'function') {
$min_lvl = ($source =~ /^[NC]OG$/) ? 'level3' : 'level4';
}
} else {
- $self->return_data({"ERROR" => "invalid min_level for m5nr/ontology: ".$min_lvl." - valid types are [".join(", ", @ont_hier)."]"}, 500);
+ $self->return_data({"ERROR" => "invalid min_level for m5nr/ontology: ".$min_lvl." - valid types are [".join(", ", @ont_hier)."]"}, 404);
}
if ( $self->cgi->param('id_map') ) {
$url .= '&id_map=1';
@@ -162,7 +167,7 @@ sub static {
if ( grep(/^$min_lvl$/, @tax_hier) ) {
$min_lvl = 'tax_'.$min_lvl;
} else {
- $self->return_data({"ERROR" => "invalid min_level for m5nr/taxonomy: ".$min_lvl." - valid types are [".join(", ", @tax_hier)."]"}, 500);
+ $self->return_data({"ERROR" => "invalid min_level for m5nr/taxonomy: ".$min_lvl." - valid types are [".join(", ", @tax_hier)."]"}, 404);
}
if ( $self->cgi->param('id_map') ) {
$url .= '&id_map=1';
@@ -175,6 +180,8 @@ sub static {
} elsif ($type eq 'sources') {
$data = $mgdb->_sources();
delete $data->{GO};
+ } else {
+ $self->return_data({"ERROR" => "Invalid resource type was entered ($type)."}, 404);
}
my $obj = { data => $data,
View
18 src/MGRAST/lib/resources2/matrix.pm
@@ -312,13 +312,13 @@ sub prepare_data {
# validate cutoffs
if (int($eval) < 1) {
- $self->return_data({"ERROR" => "invalid evalue for matrix call, must be integer greater than 1"}, 500);
+ $self->return_data({"ERROR" => "invalid evalue for matrix call, must be integer greater than 1"}, 404);
}
if ((int($ident) < 0) || (int($ident) > 100)) {
- $self->return_data({"ERROR" => "invalid identity for matrix call, must be integer between 0 and 100"}, 500);
+ $self->return_data({"ERROR" => "invalid identity for matrix call, must be integer between 0 and 100"}, 404);
}
if (int($alen) < 1) {
- $self->return_data({"ERROR" => "invalid length for matrix call, must be integer greater than 1"}, 500);
+ $self->return_data({"ERROR" => "invalid length for matrix call, must be integer greater than 1"}, 404);
}
# controlled vocabulary set
@@ -334,7 +334,7 @@ sub prepare_data {
# validate controlled vocabulary params
unless (exists $result_map->{$rtype}) {
- $self->return_data({"ERROR" => "invalid result_type for matrix call: ".$rtype." - valid types are [".join(", ", keys %$result_map)."]"}, 500);
+ $self->return_data({"ERROR" => "invalid result_type for matrix call: ".$rtype." - valid types are [".join(", ", keys %$result_map)."]"}, 404);
}
if ($type eq 'organism') {
map { $all_srcs->{$_->[0]} = 1 } @{$mgdb->sources_for_type('protein')};
@@ -346,7 +346,7 @@ sub prepare_data {
$leaf_node = 1;
}
} else {
- $self->return_data({"ERROR" => "invalid group_level for matrix call of type ".$type.": ".$group_level." - valid types are [".join(", ", @org_hier)."]"}, 500);
+ $self->return_data({"ERROR" => "invalid group_level for matrix call of type ".$type.": ".$group_level." - valid types are [".join(", ", @org_hier)."]"}, 404);
}
} elsif ($type eq 'function') {
map { $all_srcs->{$_->[0]} = 1 } grep { $_->[0] !~ /^GO/ } @{$mgdb->sources_for_type('ontology')};
@@ -359,16 +359,18 @@ sub prepare_data {
$leaf_node = 1;
}
} else {
- $self->return_data({"ERROR" => "invalid group_level for matrix call of type ".$type.": ".$group_level." - valid types are [".join(", ", @func_hier)."]"}, 500);
+ $self->return_data({"ERROR" => "invalid group_level for matrix call of type ".$type.": ".$group_level." - valid types are [".join(", ", @func_hier)."]"}, 404);
}
} elsif ($type eq 'feature') {
map { $all_srcs->{$_->[0]} = 1 } @{$mgdb->sources_for_type('protein')};
map { $all_srcs->{$_->[0]} = 1 } @{$mgdb->sources_for_type('rna')};
delete $all_srcs->{M5NR};
delete $all_srcs->{M5RNA};
+ } else {
+ $self->return_data({"ERROR" => "Invalid resource type was entered ($type)."}, 404);
}
unless (exists $all_srcs->{$source}) {
- $self->return_data({"ERROR" => "invalid source for matrix call of type ".$type.": ".$source." - valid types are [".join(", ", keys %$all_srcs)."]"}, 500);
+ $self->return_data({"ERROR" => "invalid source for matrix call of type ".$type.": ".$source." - valid types are [".join(", ", keys %$all_srcs)."]"}, 404);
}
# get data
@@ -446,7 +448,7 @@ sub prepare_data {
}
}
} else {
- $self->return_data({"ERROR" => "invalid hit_type for matrix call: ".$htype." - valid types are ['all', 'single', 'lca']"}, 500);
+ $self->return_data({"ERROR" => "invalid hit_type for matrix call: ".$htype." - valid types are ['all', 'single', 'lca']"}, 404);
}
}
} elsif ($type eq 'function') {
View
10 src/MGRAST/lib/resources2/metadata.pm
@@ -222,16 +222,16 @@ sub validate {
my $value = $self->cgi->param('value');
unless ($group && exists($groups->{$group})) {
- $self->return_data({"ERROR" => "Invalid / missing parameter 'group': ".$group." - valid types are [ '".join("', '", keys %$groups)."' ]"}, 400);
+ $self->return_data({"ERROR" => "Invalid / missing parameter 'group': ".$group." - valid types are [ '".join("', '", keys %$groups)."' ]"}, 404);
}
unless ($cat && exists($categories->{$cat})) {
- $self->return_data({"ERROR" => "Invalid / missing parameter 'category': ".$cat." - valid types are [ '".join("', '", keys %$categories)."' ]"}, 400);
+ $self->return_data({"ERROR" => "Invalid / missing parameter 'category': ".$cat." - valid types are [ '".join("', '", keys %$categories)."' ]"}, 404);
}
unless ($label) {
- $self->return_data({"ERROR" => "Missing parameter 'label'"}, 400);
+ $self->return_data({"ERROR" => "Missing parameter 'label'"}, 404);
}
unless ($value) {
- $self->return_data({"ERROR" => "Missing parameter 'value'"}, 400);
+ $self->return_data({"ERROR" => "Missing parameter 'value'"}, 404);
}
# internal name
@@ -275,7 +275,7 @@ sub validate {
my $fname = $self->cgi->param('upload');
unless ($fname) {
- $self->return_data({"ERROR" => "Invalid parameters, requires filename and data"}, 400);
+ $self->return_data({"ERROR" => "Invalid parameters, requires filename and data"}, 404);
}
if ($fname =~ /\.\./) {
$self->return_data({"ERROR" => "Invalid parameters, trying to change directory with filename, aborting"}, 400);
View
181 src/MGRAST/lib/resources2/sequence.pm
@@ -0,0 +1,181 @@
+package resources2::sequence;
+
+use strict;
+use warnings;
+no warnings('once');
+use Data::Dumper;
+
+use Conf;
+use parent qw(resources2::resource);
+
+# Override parent constructor
+sub new {
+ my ($class, @args) = @_;
+
+ # Call the constructor of the parent class
+ my $self = $class->SUPER::new(@args);
+
+ # Add name / attributes
+ $self->{name} = "sequence";
+ $self->{types} = { "organism" => 1, "function" => 1, "ontology" => 1, "feature" => 1 };
+ $self->{cutoffs} = { evalue => '5', identity => '60', length => '15' };
+ $self->{attributes} = { "streaming text" => [ 'object', [{ "col1" => ['string', 'sequence id'],
+ "col2" => ['string', 'm5nr id (md5sum)'],
+ "col3" => ['string', 'semicolon seperated list of annotations'],
+ "col4" => ['string', 'dna sequence']
+ }, "tab deliminted annotated sequence stream"] ] };
+ return $self;
+}
+
+# resource is called without any parameters
+# this method must return a description of the resource
+sub info {
+ my ($self) = @_;
+ my $content = { 'name' => $self->name,
+ 'url' => $self->cgi->url."/".$self->name,
+ 'description' => "All annotations of a metagenome for a specific annotation type and source",
+ 'type' => 'object',
+ 'documentation' => $self->cgi->url.'/api.html#'.$self->name,
+ 'requests' => [
+ { 'name' => "info",
+ 'request' => $self->cgi->url."/".$self->name,
+ 'description' => "Returns description of parameters and attributes.",
+ 'method' => "GET",
+ 'type' => "synchronous",
+ 'attributes' => "self",
+ 'parameters' => { 'required' => {},
+ 'options' => {},
+ 'body' => {} } },
+ { 'name' => "instance",
+ 'request' => $self->cgi->url."/".$self->name."/{ID}",
+ 'description' => "tab deliminted annotated sequence stream",
+ 'method' => "GET",
+ 'type' => "stream",
+ 'attributes' => $self->{attributes},
+ 'parameters' => { 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
+ 'options' => { 'evalue' => ['int', 'negative exponent value for maximum e-value cutoff: default is '.$self->{cutoffs}{evalue}],
+ 'identity' => ['int', 'percent value for minimum % identity cutoff: default is '.$self->{cutoffs}{identity}],
+ 'length' => ['int', 'value for minimum alignment length cutoff: default is '.$self->{cutoffs}{length}],
+ "type" => [ "cv", [[ "organism", "return organism data" ],
+ [ "function", "return function data" ],
+ [ "ontology", "return ontology data" ],
+ [ "feature", "return feature data" ]] ],
+ "source" => [ "cv", [[ "RefSeq", "protein database, type organism, function, feature" ],
+ [ "GenBank", "protein database, type organism, function, feature" ],
+ [ "IMG", "protein database, type organism, function, feature" ],
+ [ "SEED", "protein database, type organism, function, feature" ],
+ [ "TrEMBL", "protein database, type organism, function, feature" ],
+ [ "SwissProt", "protein database, type organism, function, feature" ],
+ [ "PATRIC", "protein database, type organism, function, feature" ],
+ [ "KEGG", "protein database, type organism, function, feature" ],
+ [ "RDP", "RNA database, type organism, function, feature" ],
+ [ "Greengenes", "RNA database, type organism, function, feature" ],
+ [ "LSU", "RNA database, type organism, function, feature" ],
+ [ "SSU", "RNA database, type organism, function, feature" ],
+ [ "Subsystems", "ontology database, type ontology only" ],
+ [ "NOG", "ontology database, type ontology only" ],
+ [ "COG", "ontology database, type ontology only" ],
+ [ "KO", "ontology database, type ontology only" ]] ] },
+ 'body' => {} } }
+ ]
+ };
+
+ $self->return_data($content);
+}
+
+# the resource is called with an id parameter
+sub instance {
+ my ($self) = @_;
+
+ # check id format
+ my $rest = $self->rest;
+ my (undef, $id) = $rest->[0] =~ /^(mgm)?(\d+\.\d+)$/;
+ if ((! $id) && scalar(@$rest)) {
+ $self->return_data( {"ERROR" => "invalid id format: " . $rest->[0]}, 400 );
+ }
+
+ # get database
+ my $master = $self->connect_to_datasource();
+
+ # get data
+ my $job = $master->Job->get_objects( {metagenome_id => $id, viewable => 1} );
+ unless ($job && scalar(@$job)) {
+ $self->return_data( {"ERROR" => "id $id does not exists"}, 404 );
+ } else {
+ $job = $job->[0];
+ }
+
+ # check rights
+ unless ($job->{public} || ($self->user && ($self->user->has_right(undef, 'view', 'metagenome', $job->{metagenome_id}) || $self->user->has_star_right('view', 'metagenome')))) {
+ $self->return_data( {"ERROR" => "insufficient permissions to view this data"}, 401 );
+ }
+
+ my $data = $self->prepare_data($job);
+ $self->return_data($data);
+}
+
+# reformat the data into the requested output format
+sub prepare_data {
+ my ($self, $data) = @_;
+
+ my $cgi = $self->cgi;
+ my $type = $cgi->param('type') ? $cgi->param('type') : 'organism';
+ my $source = $cgi->param('source') ? $cgi->param('source') : (($type eq 'ontology') ? 'Subsystems' : 'RefSeq');
+ my $eval = defined($cgi->param('evalue')) ? $cgi->param('evalue') : $self->{cutoffs}{evalue};
+ my $ident = defined($cgi->param('identity')) ? $cgi->param('identity') : $self->{cutoffs}{identity};
+ my $alen = defined($cgi->param('length')) ? $cgi->param('length') : $self->{cutoffs}{length};
+
+ my $master = $self->connect_to_datasource();
+ use MGRAST::Analysis;
+ my $mgdb = MGRAST::Analysis->new( $master->db_handle );
+ unless (ref($mgdb)) {
+ $self->return_data({"ERROR" => "resource database offline"}, 503);
+ }
+ my $mgid = $data->{metagenome_id};
+ $mgdb->set_jobs([$mgid]);
+
+ unless (exists $mgdb->_src_id->{$source}) {
+ $self->return_data({"ERROR" => "Invalid source was entered ($source). Please use one of: ".join(", ", keys %{$mgdb->_src_id})}, 404);
+ }
+ unless (exists $self->{types}{$type}) {
+ $self->return_data({"ERROR" => "Invalid type was entered ($type). Please use one of: ".join(", ", keys %{$self->{types}})}, 404);
+ }
+
+ $eval = (defined($eval) && ($eval =~ /^\d+$/)) ? "exp_avg <= " . ($eval * -1) : "";
+ $ident = (defined($ident) && ($ident =~ /^\d+$/)) ? "ident_avg >= $ident" : "";
+ $alen = (defined($alen) && ($alen =~ /^\d+$/)) ? "len_avg >= $alen" : "";
+
+ my $srcid = $mgdb->_src_id->{$source};
+ my $where = $mgdb->_get_where_str([$mgdb->_qver, "job = ".$data->{job_id}, $eval, $ident, $alen, "seek IS NOT NULL", "length IS NOT NULL"]);
+ my $query = "SELECT md5, seek, length FROM ".$mgdb->_jtbl->{md5}.$where." ORDER BY seek";
+
+ open(FILE, "<" . $mgdb->_sim_file($data->{job_id})) || $self->return_data({"ERROR" => "resource database offline"}, 503);
+ print $cgi->header(-type => 'text/plain', -status => 200, -Access_Control_Allow_Origin => '*');
+
+ foreach my $row (@{ $mgdb->_dbh->selectall_arrayref($query) }) {
+ my ($md5, $seek, $len) = @$row;
+ my $ann = [];
+ if ($type eq 'organism') {
+ $ann = $mgdb->_dbh->selectcol_arrayref("SELECT DISTINCT o.name FROM md5_annotation a, organisms_ncbi o WHERE a.md5=$md5 AND a.source=$srcid AND a.organism=o._id");
+ } elsif ($type eq 'function') {
+ $ann = $mgdb->_dbh->selectcol_arrayref("SELECT DISTINCT f.name FROM md5_annotation a, functions f WHERE a.md5=$md5 AND a.source=$srcid AND a.function=f._id");
+ } else {
+ $ann = $mgdb->_dbh->selectcol_arrayref("SELECT DISTINCT id FROM md5_annotation WHERE md5=$md5 AND source=$srcid");
+ }
+ if (@$ann == 0) { next; }
+ my $rec = '';
+ seek(FILE, $seek, 0);
+ read(FILE, $rec, $len);
+ chomp $rec;
+ foreach my $line ( split(/\n/, $rec) ) {
+ my @tabs = split(/\t/, $line);
+ if (@tabs == 13) {
+ print join("\t", ('mgm'.$mgid."|".$tabs[0], $tabs[1], join(";", @$ann), $tabs[12]))."\n";
+ }
+ }
+ }
+ close FILE;
+ exit 0;
+}
+
+1;
View
174 src/MGRAST/lib/resources2/sequences.pm
@@ -1,174 +0,0 @@
-package resources2::sequences;
-
-use strict;
-use warnings;
-no warnings('once');
-
-use Conf;
-use parent qw(resources2::resource);
-
-# Override parent constructor
-sub new {
- my ($class, @args) = @_;
-
- # Call the constructor of the parent class
- my $self = $class->SUPER::new(@args);
-
- # Add name / attributes
- $self->{name} = "sequences";
- $self->{attributes} = { "id" => [ 'string', 'unique object identifier' ],
- "data" => [ 'hash', [ { 'key' => ['string', 'annotation or md5 text'],
- 'value' => ['list', ['tuple', 'read id and read sequence']] },
- 'data type pointing at lists of sequence info' ]],
- "version" => [ 'integer', 'version of the object' ],
- "url" => [ 'uri', 'resource location of this object instance' ] };
- return $self;
-}
-
-# resource is called without any parameters
-# this method must return a description of the resource
-sub info {
- my ($self) = @_;
- my $content = { 'name' => $self->name,
- 'url' => $self->cgi->url."/".$self->name,
- 'description' => "A set of genomic sequences of a metagenome annotated by a specified source",
- 'type' => 'object',
- 'documentation' => $self->cgi->url.'/api.html#'.$self->name,
- 'requests' => [ { 'name' => "info",
- 'request' => $self->cgi->url."/".$self->name,
- 'description' => "Returns description of parameters and attributes.",
- 'method' => "GET" ,
- 'type' => "synchronous" ,
- 'attributes' => "self",
- 'parameters' => { 'options' => {},
- 'required' => {},
- 'body' => {} } },
- { 'name' => "md5",
- 'request' => $self->cgi->url."/".$self->name."/{ID}",
- 'description' => "Returns a single data object.",
- 'method' => "GET" ,
- 'type' => "synchronous" ,
- 'attributes' => $self->attributes,
- 'parameters' => { 'options' => { "sequence_type" => [ "cv", [ [ "dna", "return DNA sequences" ],
- [ "protein", "return protein sequences" ] ] ],
- "md5" => [ "list", [ "string", "md5 identifier" ] ] },
- 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
- 'body' => { } } },
- { 'name' => "annotation",
- 'request' => $self->cgi->url."/".$self->name."/{ID}",
- 'description' => "Returns a single data object.",
- 'method' => "GET" ,
- 'type' => "synchronous" ,
- 'attributes' => $self->attributes,
- 'parameters' => { 'options' => { "data_type" => [ "cv", [ [ "organism", "return organism data" ],
- [ "function", "return function data" ],
- [ "ontology", "return ontology data" ] ] ],
- "sequence_type" => [ "cv", [ [ "dna", "return DNA sequences" ],
- [ "protein", "return protein sequences" ] ] ],
- "annotation" => [ "list", [ "string", "data_type to filter by" ] ],
- "source" => [ "cv", [[ "RefSeq", "protein database, type organism and function only" ],
- [ "GenBank", "protein database, type organism and function only" ],
- [ "IMG", "protein database, type organism and function only" ],
- [ "SEED", "protein database, type organism and function only" ],
- [ "TrEMBL", "protein database, type organism and function only" ],
- [ "SwissProt", "protein database, type organism and function only" ],
- [ "PATRIC", "protein database, type organism and function only" ],
- [ "KEGG", "protein database, type organism and function only" ],
- [ "RDP", "RNA database, type organism and function only" ],
- [ "Greengenes", "RNA database, type organism and function only" ],
- [ "LSU", "RNA database, type organism and function only" ],
- [ "SSU", "RNA database, type organism and function only" ],
- [ "Subsystems", "ontology database, type ontology only" ],
- [ "NOG", "ontology database, type ontology only" ],
- [ "COG", "ontology database, type ontology only" ],
- [ "KO", "ontology database, type ontology only" ]] ] },
- 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
- 'body' => { } } }
- ]
- };
-
- $self->return_data($content);
-}
-
-# the resource is called with an id parameter
-sub instance {
- my ($self) = @_;
-
- # check id format
- my $rest = $self->rest;
- my (undef, $id) = $rest->[0] =~ /^(mgm)?(\d+\.\d+)$/;
- if ((! $id) && scalar(@$rest)) {
- $self->return_data( {"ERROR" => "invalid id format: " . $rest->[0]}, 400 );
- }
-
- # get database
- my $master = $self->connect_to_datasource();
-
- # get data
- my $job = $master->Job->get_objects( {metagenome_id => $id, viewable => 1} );
- unless ($job && scalar(@$job)) {
- $self->return_data( {"ERROR" => "id $id does not exists"}, 404 );
- } else {
- $job = $job->[0];
- }
-
- # check rights
- unless ($job->{public} || ($self->user && ($self->user->has_right(undef, 'view', 'metagenome', $job->{metagenome_id}) || $self->user->has_star_right('view', 'metagenome')))) {
- $self->return_data( {"ERROR" => "insufficient permissions to view this data"}, 401 );
- }
-
- # prepare data
- my $data = $self->prepare_data($job);
-
- $self->return_data($data);
-}
-
-# reformat the data into the requested output format
-sub prepare_data {
- my ($self, $data) = @_;
-
- my $cgi = $self->cgi;
- my $type = $cgi->param('data_type') ? $cgi->param('data_type') : 'organism';
- my $seq = $cgi->param('sequence_type') ? $cgi->param('sequence_type') : 'dna';
- my @srcs = $cgi->param('source') ? $cgi->param('source') : ();
- my @anns = $cgi->param('annotation') ? $cgi->param('annotation') : ();
- my @md5s = $cgi->param('md5') ? $cgi->param('md5') : ();
-
- my $master = $self->connect_to_datasource();
- use MGRAST::Analysis;
- my $mgdb = MGRAST::Analysis->new( $master->db_handle );
- unless (ref($mgdb)) {
- $self->return_data( {"ERROR" => "resource database offline"}, 503 );
- }
-
- my $url = $cgi->url."/sequences/mgm".$data->{metagenome_id}."?sequence_type=".$seq;
- my $content;
- if (scalar(@md5s) > 0) {
- my $md5_ints_to_strings = $mgdb->_get_annotation_map('md5', \@md5s);
- if (scalar(keys %$md5_ints_to_strings) > 0) {
- $content = $mgdb->sequences_for_md5s($data->{metagenome_id}, $seq, [keys %$md5_ints_to_strings], 1);
- my %valid_md5s = map { $_ => 1} values %$md5_ints_to_strings; # uniquifying valid md5s
- $url .= "&md5=".join("&md5=", keys %valid_md5s);
- } else {
- $self->return_data( {"ERROR" => "No valid md5 was entered. For more information on how to use this resource, view the resource description here: ".$cgi->url."/sequences"}, 404 );
- }
- } elsif (scalar(@anns) > 0) {
- $content = $mgdb->sequences_for_annotation($data->{metagenome_id}, $seq, $type, \@srcs, \@anns);
- $url .= "&data_type=".$type."&annotation=".join("&annotation=", @anns);
- if (scalar(@srcs) > 0) {
- $url .= "&source=".join("&source=", @srcs);
- }
- } else {
- $self->return_data( {"ERROR" => "To retrieve sequences, you must either enter an 'md5' or a 'data_type' and an 'annotation'. The default 'data_type' is organism. For more information on how to use this resource, view the resource description here: ".$cgi->url."/sequences"}, 404 );
- }
-
- my $object = { id => "mgm".$data->{metagenome_id},
- data => $content,
- url => $url,
- version => 1
- };
-
- return $object;
-}
-
-1;
View
188 src/MGRAST/lib/resources2/similarity.pm
@@ -0,0 +1,188 @@
+package resources2::similarity;
+
+use strict;
+use warnings;
+no warnings('once');
+use Data::Dumper;
+
+use Conf;
+use parent qw(resources2::resource);
+
+# Override parent constructor
+sub new {
+ my ($class, @args) = @_;
+
+ # Call the constructor of the parent class
+ my $self = $class->SUPER::new(@args);
+
+ # Add name / attributes
+ $self->{name} = "similarity";
+ $self->{types} = { "organism" => 1, "function" => 1, "ontology" => 1, "feature" => 1 };
+ $self->{cutoffs} = { evalue => '5', identity => '60', length => '15' };
+ $self->{attributes} = { "streaming text" => [ 'object', [{ "col1" => ['string', 'query sequence id'],
+ "col2" => ['string', 'hit m5nr id (md5sum)'],
+ "col3" => ['float', 'percentage identity'],
+ "col4" => ['int', 'alignment length,'],
+ "col5" => ['int', 'number of mismatches'],
+ "col6" => ['int', 'number of gap openings'],
+ "col7" => ['int', 'query start'],
+ "col8" => ['int', 'query end'],
+ "col9" => ['int', 'hit start'],
+ "col10" => ['int', 'hit end'],
+ "col11" => ['float', 'e-value'],
+ "col12" => ['float', 'bit score'],
+ "col13" => ['string', 'semicolon seperated list of annotations']
+ }, "tab deliminted blast m8 with annotation"] ] };
+ return $self;
+}
+
+# resource is called without any parameters
+# this method must return a description of the resource
+sub info {
+ my ($self) = @_;
+ my $content = { 'name' => $self->name,
+ 'url' => $self->cgi->url."/".$self->name,
+ 'description' => "All annotations of a metagenome for a specific annotation type and source",
+ 'type' => 'object',
+ 'documentation' => $self->cgi->url.'/api.html#'.$self->name,
+ 'requests' => [
+ { 'name' => "info",
+ 'request' => $self->cgi->url."/".$self->name,
+ 'description' => "Returns description of parameters and attributes.",
+ 'method' => "GET",
+ 'type' => "synchronous",
+ 'attributes' => "self",
+ 'parameters' => { 'required' => {},
+ 'options' => {},
+ 'body' => {} } },
+ { 'name' => "instance",
+ 'request' => $self->cgi->url."/".$self->name."/{ID}",
+ 'description' => "tab deliminted blast m8 with annotation",
+ 'method' => "GET",
+ 'type' => "stream",
+ 'attributes' => $self->{attributes},
+ 'parameters' => { 'required' => { "id" => [ "string", "unique metagenome identifier" ] },
+ 'options' => { 'evalue' => ['int', 'negative exponent value for maximum e-value cutoff: default is '.$self->{cutoffs}{evalue}],
+ 'identity' => ['int', 'percent value for minimum % identity cutoff: default is '.$self->{cutoffs}{identity}],
+ 'length' => ['int', 'value for minimum alignment length cutoff: default is '.$self->{cutoffs}{length}],
+ "type" => [ "cv", [[ "organism", "return organism data" ],
+ [ "function", "return function data" ],
+ [ "ontology", "return ontology data" ],
+ [ "feature", "return feature data" ]] ],
+ "source" => [ "cv", [[ "RefSeq", "protein database, type organism, function, feature" ],
+ [ "GenBank", "protein database, type organism, function, feature" ],
+ [ "IMG", "protein database, type organism, function, feature" ],
+ [ "SEED", "protein database, type organism, function, feature" ],
+ [ "TrEMBL", "protein database, type organism, function, feature" ],
+ [ "SwissProt", "protein database, type organism, function, feature" ],
+ [ "PATRIC", "protein database, type organism, function, feature" ],
+ [ "KEGG", "protein database, type organism, function, feature" ],
+ [ "RDP", "RNA database, type organism, function, feature" ],
+ [ "Greengenes", "RNA database, type organism, function, feature" ],
+ [ "LSU", "RNA database, type organism, function, feature" ],
+ [ "SSU", "RNA database, type organism, function, feature" ],
+ [ "Subsystems", "ontology database, type ontology only" ],
+ [ "NOG", "ontology database, type ontology only" ],
+ [ "COG", "ontology database, type ontology only" ],
+ [ "KO", "ontology database, type ontology only" ]] ] },
+ 'body' => {} } }
+ ]
+ };
+
+ $self->return_data($content);
+}
+
+# the resource is called with an id parameter
+sub instance {
+ my ($self) = @_;
+
+ # check id format
+ my $rest = $self->rest;
+ my (undef, $id) = $rest->[0] =~ /^(mgm)?(\d+\.\d+)$/;
+ if ((! $id) && scalar(@$rest)) {
+ $self->return_data( {"ERROR" => "invalid id format: " . $rest->[0]}, 400 );
+ }
+
+ # get database
+ my $master = $self->connect_to_datasource();
+
+ # get data
+ my $job = $master->Job->get_objects( {metagenome_id => $id, viewable => 1} );
+ unless ($job && scalar(@$job)) {
+ $self->return_data( {"ERROR" => "id $id does not exists"}, 404 );
+ } else {
+ $job = $job->[0];
+ }
+
+ # check rights
+ unless ($job->{public} || ($self->user && ($self->user->has_right(undef, 'view', 'metagenome', $job->{metagenome_id}) || $self->user->has_star_right('view', 'metagenome')))) {
+ $self->return_data( {"ERROR" => "insufficient permissions to view this data"}, 401 );
+ }
+
+ my $data = $self->prepare_data($job);
+ $self->return_data($data);
+}
+
+# reformat the data into the requested output format
+sub prepare_data {
+ my ($self, $data) = @_;
+
+ my $cgi = $self->cgi;
+ my $type = $cgi->param('type') ? $cgi->param('type') : 'organism';
+ my $source = $cgi->param('source') ? $cgi->param('source') : (($type eq 'ontology') ? 'Subsystems' : 'RefSeq');
+ my $eval = defined($cgi->param('evalue')) ? $cgi->param('evalue') : $self->{cutoffs}{evalue};
+ my $ident = defined($cgi->param('identity')) ? $cgi->param('identity') : $self->{cutoffs}{identity};
+ my $alen = defined($cgi->param('length')) ? $cgi->param('length') : $self->{cutoffs}{length};
+
+ my $master = $self->connect_to_datasource();
+ use MGRAST::Analysis;
+ my $mgdb = MGRAST::Analysis->new( $master->db_handle );
+ unless (ref($mgdb)) {
+ $self->return_data({"ERROR" => "resource database offline"}, 503);
+ }
+ my $mgid = $data->{metagenome_id};
+ $mgdb->set_jobs([$mgid]);
+
+ unless (exists $mgdb->_src_id->{$source}) {
+ $self->return_data({"ERROR" => "Invalid source was entered ($source). Please use one of: ".join(", ", keys %{$mgdb->_src_id})}, 404);
+ }
+ unless (exists $self->{types}{$type}) {
+ $self->return_data({"ERROR" => "Invalid type was entered ($type). Please use one of: ".join(", ", keys %{$self->{types}})}, 404);
+ }
+
+ $eval = (defined($eval) && ($eval =~ /^\d+$/)) ? "exp_avg <= " . ($eval * -1) : "";
+ $ident = (defined($ident) && ($ident =~ /^\d+$/)) ? "ident_avg >= $ident" : "";
+ $alen = (defined($alen) && ($alen =~ /^\d+$/)) ? "len_avg >= $alen" : "";
+
+ my $srcid = $mgdb->_src_id->{$source};
+ my $where = $mgdb->_get_where_str([$mgdb->_qver, "job = ".$data->{job_id}, $eval, $ident, $alen, "seek IS NOT NULL", "length IS NOT NULL"]);
+ my $query = "SELECT md5, seek, length FROM ".$mgdb->_jtbl->{md5}.$where." ORDER BY seek";
+
+ open(FILE, "<" . $mgdb->_sim_file($data->{job_id})) || $self->return_data({"ERROR" => "resource database offline"}, 503);
+ print $cgi->header(-type => 'text/plain', -status => 200, -Access_Control_Allow_Origin => '*');
+
+ foreach my $row (@{ $mgdb->_dbh->selectall_arrayref($query) }) {
+ my ($md5, $seek, $len) = @$row;
+ my $ann = [];
+ if ($type eq 'organism') {
+ $ann = $mgdb->_dbh->selectcol_arrayref("SELECT DISTINCT o.name FROM md5_annotation a, organisms_ncbi o WHERE a.md5=$md5 AND a.source=$srcid AND a.organism=o._id");
+ } elsif ($type eq 'function') {
+ $ann = $mgdb->_dbh->selectcol_arrayref("SELECT DISTINCT f.name FROM md5_annotation a, functions f WHERE a.md5=$md5 AND a.source=$srcid AND a.function=f._id");
+ } else {
+ $ann = $mgdb->_dbh->selectcol_arrayref("SELECT DISTINCT id FROM md5_annotation WHERE md5=$md5 AND source=$srcid");
+ }
+ if (@$ann == 0) { next; }
+ my $rec = '';
+ seek(FILE, $seek, 0);
+ read(FILE, $rec, $len);
+ chomp $rec;
+ foreach my $line ( split(/\n/, $rec) ) {
+ my @tabs = split(/\t/, $line);
+ print join("\t", ('mgm'.$mgid."|".$tabs[0], @tabs[1..11], join(";", @$ann)))."\n";
+ }
+ }
+ close FILE;
+ exit 0;
+}
+
+1;
View
6 src/WebApplication/scripts/api2html.pl
@@ -90,7 +90,7 @@ sub usage {
$html .= "</p><h3>Parameters</h3><ul>";
# iterate over paramaters
foreach my $ptype (sort keys %param_types) {
- foreach my $param (keys(%{$req->{parameters}->{$ptype}})) {
+ foreach my $param (sort keys(%{$req->{parameters}->{$ptype}})) {
my $pm = $req->{parameters}->{$ptype}->{$param};
$pm->[0] =~ s/cv/controlled vocabulary/;
$html .= "<li><b>$param</b> (".$pm->[0];
@@ -115,7 +115,7 @@ sub usage {
$html .= "</ul>";
$html .= "<h3>Return Attributes</h3><ul>";
# iterate over attributes
- foreach my $param (keys(%{$req->{attributes}})) {
+ foreach my $param (sort keys(%{$req->{attributes}})) {
my ($att_obj, $att_hash);
my $att = $param;
my $att_type = $req->{attributes}->{$param}->[0];
@@ -141,7 +141,7 @@ sub usage {
$html .= "<li><b>$att</b> ($att_type)</li><p>";
if ($att_obj) {
$html .= "This attribute has an object structure:</p><ul style='list-style: none;'>";
- foreach my $key (keys(%$att_obj)) {
+ foreach my $key (sort keys(%$att_obj)) {
my $obj_type = $att_obj->{$key}->[0];
my $obj_att = $att_obj->{$key}->[1];
while (ref($obj_att) eq 'ARRAY') {
Something went wrong with that request. Please try again.