brapi refactor error response
[sgn.git] / lib / CXGN / BrAPI / v1 / Germplasm.pm
blobf3c67002c06af3a34e0f1f8bbde0df36a3461cdc
1 package CXGN::BrAPI::v1::Germplasm;
3 use Moose;
4 use Data::Dumper;
5 use SGN::Model::Cvterm;
6 use CXGN::Trial;
7 use CXGN::Chado::Stock;
8 use CXGN::BrAPI::Pagination;
9 use CXGN::BrAPI::ErrorResponse;
11 has 'bcs_schema' => (
12 isa => 'Bio::Chado::Schema',
13 is => 'rw',
14 required => 1,
17 has 'metadata_schema' => (
18 isa => 'CXGN::Metadata::Schema',
19 is => 'rw',
20 required => 1,
23 has 'phenome_schema' => (
24 isa => 'CXGN::Phenome::Schema',
25 is => 'rw',
26 required => 1,
29 has 'page_size' => (
30 isa => 'Int',
31 is => 'rw',
32 required => 1,
35 has 'page' => (
36 isa => 'Int',
37 is => 'rw',
38 required => 1,
41 has 'status' => (
42 isa => 'ArrayRef[Maybe[HashRef]]',
43 is => 'rw',
44 required => 1,
47 sub germplasm_search {
48 my $self = shift;
49 my $search_params = shift;
51 my $page_size = $self->page_size;
52 my $page = $self->page;
53 my $status = $self->status;
55 my @germplasm_names = $search_params->{germplasmName} ? @{$search_params->{germplasmName}} : ();
56 my @accession_numbers = $search_params->{accessionNumber} ? @{$search_params->{accessionNumber}} : ();
57 my @genus = $search_params->{germplasmGenus} ? @{$search_params->{germplasmGenus}} : ();
58 my $subtaxa = $search_params->{germplasmSubTaxa}->[0];
59 my @species = $search_params->{germplasmSpecies} ? @{$search_params->{germplasmSpecies}} : ();
60 my @germplasm_ids = $search_params->{germplasmDbId} ? @{$search_params->{germplasmDbId}} : ();
61 my @germplasm_puis = $search_params->{germplasmPUI} ? @{$search_params->{germplasmPUI}} : ();
62 my $match_method = $search_params->{matchMethod}->[0];
63 my %result;
65 if ($match_method && ($match_method ne 'exact' && $match_method ne 'wildcard')) {
66 push @$status, { 'error' => "matchMethod '$match_method' not recognized. Allowed matchMethods: wildcard, exact. Wildcard allows % or * for multiple characters and ? for single characters." };
68 my $total_count = 0;
70 my $accession_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
71 my %search_params;
72 my @join_params;
74 $search_params{'me.type_id'} = $accession_type_cvterm_id;
76 if (@germplasm_names && scalar(@germplasm_names)>0){
77 if (!$match_method || $match_method eq 'exact') {
78 $search_params{'me.uniquename'} = \@germplasm_names;
79 } elsif ($match_method eq 'wildcard') {
80 my @wildcard_names;
81 foreach (@germplasm_names) {
82 $_ =~ tr/*?/%_/;
83 push @wildcard_names, $_;
85 $search_params{'me.uniquename'} = { 'ilike' => \@wildcard_names };
89 if (@germplasm_ids && scalar(@germplasm_ids)>0){
90 if (!$match_method || $match_method eq 'exact') {
91 $search_params{'me.stock_id'} = \@germplasm_ids;
92 } elsif ($match_method eq 'wildcard') {
93 my @wildcard_ids;
94 foreach (@germplasm_ids) {
95 $_ =~ tr/*?/%_/;
96 push @wildcard_ids, $_;
98 $search_params{'me.stock_id::varchar(255)'} = { 'ilike' => \@wildcard_ids };
102 #print STDERR Dumper \%search_params;
103 #$self->bcs_schema->storage->debug(1);
104 my $accession_number_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'accession number', 'stock_property')->cvterm_id();
105 if (@accession_numbers && scalar(@accession_numbers)>0) {
106 $search_params{'stockprops.type_id'} = $accession_number_cvterm_id;
107 $search_params{'stockprops.value'} = \@accession_numbers;
108 push @join_params, 'stockprops';
110 my $accession_pui_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'PUI', 'stock_property')->cvterm_id();
111 if (@germplasm_puis && scalar(@germplasm_puis)>0) {
112 $search_params{'stockprops.type_id'} = $accession_pui_cvterm_id;
113 $search_params{'stockprops.value'} = \@germplasm_puis;
114 push @join_params, 'stockprops';
116 if (@genus && scalar(@genus)>0) {
117 $search_params{'organism.genus'} = \@genus;
119 if (@species && scalar(@species)>0) {
120 $search_params{'organism.species'} = \@species;
123 push @join_params, 'organism';
124 my $rs = $self->bcs_schema()->resultset("Stock::Stock")->search( \%search_params, {join=>\@join_params, '+select'=>['organism.genus', 'organism.species', 'organism.common_name'], '+as'=>['genus','species','common_name'], order_by=>'me.uniquename'} );
126 my @data;
127 if ($rs) {
128 $total_count = $rs->count();
129 my $rs_slice = $rs->slice($page_size*$page, $page_size*($page+1)-1);
130 while (my $stock = $rs_slice->next()) {
131 my $stockprop_hash = CXGN::Chado::Stock->new($self->bcs_schema, $stock->stock_id)->get_stockprop_hash();
132 my @donor_array;
133 my $donor_accessions = $stockprop_hash->{'donor'} ? $stockprop_hash->{'donor'} : [];
134 my $donor_institutes = $stockprop_hash->{'donor institute'} ? $stockprop_hash->{'donor institute'} : [];
135 my $donor_puis = $stockprop_hash->{'donor PUI'} ? $stockprop_hash->{'donor PUI'} : [];
136 for (0 .. scalar(@$donor_accessions)){
137 push @donor_array, { 'donorGermplasmName'=>$donor_accessions->[$_], 'donorAccessionNumber'=>$donor_accessions->[$_], 'donorInstituteCode'=>$donor_institutes->[$_], 'germplasmPUI'=>$donor_puis->[$_] };
139 push @data, {
140 germplasmDbId=>$stock->stock_id,
141 defaultDisplayName=>$stock->uniquename,
142 germplasmName=>$stock->uniquename,
143 accessionNumber=>$stockprop_hash->{'accession number'} ? join ',', @{$stockprop_hash->{'accession number'}} : '',
144 germplasmPUI=>$stockprop_hash->{'PUI'} ? join ',', @{$stockprop_hash->{'PUI'}} : '',
145 pedigree=>$self->germplasm_pedigree_string($stock->stock_id),
146 germplasmSeedSource=>$stockprop_hash->{'seed source'} ? join ',', @{$stockprop_hash->{'seed source'}} : '',
147 synonyms=> $stockprop_hash->{'stock_synonym'} ? join ',', @{$stockprop_hash->{'stock_synonym'}} : '',
148 commonCropName=>$stock->get_column('common_name'),
149 instituteCode=>$stockprop_hash->{'institute code'} ? join ',', @{$stockprop_hash->{'institute code'}} : '',
150 instituteName=>$stockprop_hash->{'institute name'} ? join ',', @{$stockprop_hash->{'institute name'}} : '',
151 biologicalStatusOfAccessionCode=>$stockprop_hash->{'biological status of accession code'} ? join ',', @{$stockprop_hash->{'biological status of accession code'}} : '',
152 countryOfOriginCode=>$stockprop_hash->{'country of origin'} ? join ',', @{$stockprop_hash->{'country of origin'}} : '',
153 typeOfGermplasmStorageCode=>$stockprop_hash->{'type of germplasm storage code'} ? join ',', @{$stockprop_hash->{'type of germplasm storage code'}} : '',
154 genus=>$stock->get_column('genus'),
155 species=>$stock->get_column('species'),
156 speciesAuthority=>'',
157 subtaxa=>'',
158 subtaxaAuthority=>'',
159 donors=>\@donor_array,
160 acquisitionDate=>'',
165 %result = (data => \@data);
166 push @$status, { 'success' => 'Germplasm-search result constructed' };
167 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
168 my $response = {
169 'status' => $status,
170 'pagination' => $pagination,
171 'result' => \%result,
172 'datafiles' => []
174 return $response;
177 sub germplasm_pedigree_string {
178 my $self = shift;
179 my $stock_id = shift;
180 my $s = CXGN::Chado::Stock->new($self->bcs_schema, $stock_id);
181 my $pedigree_root = $s->get_parents('1');
182 my $pedigree_string = $pedigree_root ? $pedigree_root->get_pedigree_string('1') : '';
183 return $pedigree_string;
186 sub germplasm_detail {
187 my $self = shift;
188 my $stock_id = shift;
189 my $status = $self->status;
190 my %result;
192 my $verify_id = $self->bcs_schema->resultset('Stock::Stock')->find({stock_id=>$stock_id});
193 my $stock = CXGN::Chado::Stock->new($self->bcs_schema(), $stock_id);
195 my $total_count = 0;
196 if ($verify_id) {
197 $total_count = 1;
198 } else {
199 push @$status, { 'error' => 'GermplasmDbId does not exist in the database' };
200 return CXGN::BrAPI::ErrorResponse->return_error($status);
202 my $stockprop_hash = $stock->get_stockprop_hash();
204 my @donor_array;
205 my $donor_accessions = $stockprop_hash->{'donor'} ? $stockprop_hash->{'donor'} : [];
206 my $donor_institutes = $stockprop_hash->{'donor institute'} ? $stockprop_hash->{'donor institute'} : [];
207 my $donor_puis = $stockprop_hash->{'donor PUI'} ? $stockprop_hash->{'donor PUI'} : [];
208 for (0 .. scalar(@$donor_accessions)){
209 push @donor_array, { 'donorGermplasmName'=>$donor_accessions->[$_], 'donorAccessionNumber'=>$donor_accessions->[$_], 'donorInstituteCode'=>$donor_institutes->[$_], 'germplasmPUI'=>$donor_puis->[$_] };
212 %result = (
213 germplasmDbId=>$stock_id,
214 defaultDisplayName=>$stock->get_name(),
215 germplasmName=>$stock->get_uniquename(),
216 accessionNumber=>$stock->get_uniquename(),
217 germplasmPUI=>$stock->get_uniquename(),
218 pedigree=>$self->germplasm_pedigree_string($stock_id),
219 germplasmSeedSource=>$stockprop_hash->{'seed source'} ? join ',', @{$stockprop_hash->{'seed source'}} : '',
220 synonyms=>$stockprop_hash->{'stock_synonym'} ? join ',', @{$stockprop_hash->{'stock_synonym'}} : '',
221 commonCropName=>$stock->get_organism->common_name(),
222 instituteCode=>$stockprop_hash->{'institute code'} ? join ',', @{$stockprop_hash->{'institute code'}} : '',
223 instituteName=>$stockprop_hash->{'institute name'} ? join ',', @{$stockprop_hash->{'institute name'}} : '',
224 biologicalStatusOfAccessionCode=>$stockprop_hash->{'biological status of accession code'} ? join ',', @{$stockprop_hash->{'biological status of accession code'}} : '',
225 countryOfOriginCode=>$stockprop_hash->{'country of origin'} ? join ',', @{$stockprop_hash->{'country of origin'}} : '',
226 typeOfGermplasmStorageCode=>$stockprop_hash->{'type of germplasm storage code'} ? join ',', @{$stockprop_hash->{'type of germplasm storage code'}} : '',
227 genus=>$stock->get_organism->genus(),
228 species=>$stock->get_organism->species(),
229 speciesAuthority=>'',
230 subtaxa=>'',
231 subtaxaAuthority=>'',
232 donors=>\@donor_array,
233 acquisitionDate=>'',
235 push @$status, { 'success' => 'Germplasm-search result constructed' };
236 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,1,0);
237 my $response = {
238 'status' => $status,
239 'pagination' => $pagination,
240 'result' => \%result,
241 'datafiles' => []
243 return $response;
246 sub germplasm_pedigree {
247 my $self = shift;
248 my $inputs = shift;
249 my $stock_id = $inputs->{stock_id};
250 my $notation = $inputs->{notation};
251 my $status = $self->status;
252 if ($notation) {
253 push @$status, { 'info' => 'Notation not yet implemented. Returns a simple parent1/parent2 string.' };
254 if ($notation ne 'purdy') {
255 push @$status, { 'error' => 'Unsupported notation code. Allowed notation: purdy' };
259 my %result;
260 my $total_count = 0;
261 my $s = CXGN::Chado::Stock->new($self->bcs_schema(), $stock_id);
262 if ($s) {
263 $total_count = 1;
264 my @direct_parents = $s->get_direct_parents();
265 %result = (
266 germplasmDbId=>$stock_id,
267 pedigree=>$self->germplasm_pedigree_string($stock_id),
268 parent1Id=>$direct_parents[0][0],
269 parent2Id=>$direct_parents[1][0]
273 push @$status, { 'success' => 'Germplasm-pedigree result constructed' };
274 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,1,0);
275 my $response = {
276 'status' => $status,
277 'pagination' => $pagination,
278 'result' => \%result,
279 'datafiles' => []
281 return $response;
284 sub germplasm_markerprofiles {
285 my $self = shift;
286 my $stock_id = shift;
288 my $page_size = $self->page_size;
289 my $page = $self->page;
290 my $status = $self->status;
291 my @marker_profiles;
293 my $snp_genotyping_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'snp genotyping', 'genotype_property')->cvterm_id();
295 my $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
296 {'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'stock.stock_id'=>$stock_id},
297 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
298 select=> ['genotypeprops.genotypeprop_id'],
299 as=> ['genotypeprop_id'],
300 order_by=>{ -asc=>'genotypeprops.genotypeprop_id' }
304 my $rs_slice = $rs->slice($page_size*$page, $page_size*($page+1)-1);
305 while (my $gt = $rs_slice->next()) {
306 push @marker_profiles, $gt->get_column('genotypeprop_id');
308 my $total_count = scalar(@marker_profiles);
309 my %result = (
310 germplasmDbId=>$stock_id,
311 markerProfiles=>\@marker_profiles
313 push @$status, { 'success' => 'Germplasm-markerprofiles result constructed' };
314 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
315 my $response = {
316 'status' => $status,
317 'pagination' => $pagination,
318 'result' => \%result,
319 'datafiles' => []
321 return $response;