calc plot pheno
[sgn.git] / lib / SGN / Controller / AJAX / BrAPI.pm
blob8a722a13cae198e409f47de21d7b07eeec312df5
2 package SGN::Controller::AJAX::BrAPI;
4 use Moose;
5 use JSON::Any;
6 use Data::Dumper;
8 use POSIX;
9 use CXGN::BreedersToolbox::Projects;
10 use CXGN::Trial;
11 use CXGN::Trial::TrialLayout;
12 use CXGN::Chado::Stock;
13 use CXGN::Login;
14 use CXGN::BreederSearch;
15 use CXGN::Trial::TrialCreate;
16 use JSON qw( decode_json );
17 use Data::Dumper;
18 use Try::Tiny;
20 BEGIN { extends 'Catalyst::Controller::REST' };
22 __PACKAGE__->config(
23 default => 'application/json',
24 stash_key => 'rest',
25 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
28 has 'bcs_schema' => ( isa => 'Bio::Chado::Schema',
29 is => 'rw',
32 my $DEFAULT_PAGE_SIZE=20;
35 sub brapi : Chained('/') PathPart('brapi') CaptureArgs(1) {
36 my $self = shift;
37 my $c = shift;
38 my $version = shift;
39 my @status;
41 $self->bcs_schema( $c->dbic_schema("Bio::Chado::Schema") );
42 $c->stash->{api_version} = $version;
43 $c->response->headers->header( "Access-Control-Allow-Origin" => '*' );
44 $c->stash->{status} = \@status;
45 $c->stash->{session_token} = $c->req->param("session_token");
46 $c->stash->{current_page} = $c->req->param("currentPage") || 1;
47 $c->stash->{page_size} = $c->req->param("pageSize") || $DEFAULT_PAGE_SIZE;
51 sub _authenticate_user {
52 my $c = shift;
53 my $status = $c->stash->{status};
54 my @status = @$status;
56 my ($person_id, $user_type, $user_pref, $expired) = CXGN::Login->new($c->dbc->dbh)->query_from_cookie($c->stash->{session_token});
57 #print STDERR $person_id." : ".$user_type." : ".$expired;
59 if (!$person_id || $expired || $user_type ne 'curator') {
60 push(@status, 'You must login and have permission to access BrAPI calls.');
61 my %metadata = (status=>\@status);
62 $c->stash->{rest} = \%metadata;
63 $c->detach;
66 return 1;
69 =head2 /brapi/v1/token
71 Usage: For logging a user in and loggin a user out through the API
72 Desc:
74 For Logging In
75 POST Request:
77 "grant_type" : "password", //(optional, text, `password`) ... The grant type, only allowed value is password, but can be ignored
78 "username" : "user38", // (required, text, `thepoweruser`) ... The username
79 "password" : "secretpw", // (optional, text, `mylittlesecret`) ... The password
80 "client_id" : "blabla" // (optional, text, `blabla`) ... The client id, currently ignored.
83 POST Response:
85 "metadata": {
86 "pagination": {},
87 "status": {},
88 "datafiles": []
90 "userDisplayName": "John Smith",
91 "access_token": "R6gKDBRxM4HLj6eGi4u5HkQjYoIBTPfvtZzUD8TUzg4",
92 "expires_in": "The lifetime in seconds of the access token"
95 For Logging out
96 DELETE Request:
99 "access_token" : "R6gKDBRxM4HLj6eGi4u5HkQjYoIBTPfvtZzUD8TUzg4" // (optional, text, `R6gKDBRxM4HLj6eGi4u5HkQjYoIBTPfvtZzUD8TUzg4`) ... The user access token. Default: current user token.
102 DELETE Response:
104 "metadata": {
105 "pagination" : {},
106 "status" : { "message" : "User has been logged out successfully."},
107 "datafiles": []
109 "result" : {}
112 =cut
114 sub authenticate_token : Chained('brapi') PathPart('token') Args(0) : ActionClass('REST') { }
116 sub authenticate_token_DELETE {
117 my $self = shift;
118 my $c = shift;
120 my $login_controller = CXGN::Login->new($c->dbc->dbh);
122 my $status = $c->stash->{status};
123 my @status = @$status;
125 $login_controller->logout_user();
127 my %pagination = ();
128 my %result;
129 my @data_files;
130 my %metadata = (pagination=>\%pagination, status=>\@status, datafiles=>\@data_files);
131 my %response = (metadata=>\%metadata, result=>\%result);
132 $c->stash->{rest} = \%response;
135 sub authenticate_token_POST {
136 my $self = shift;
137 my $c = shift;
139 my $login_controller = CXGN::Login->new($c->dbc->dbh);
140 my $params = $c->req->params();
142 my $status = $c->stash->{status};
143 my @status = @$status;
144 my $cookie = '';
145 my $first_name = '';
146 my $last_name = '';
148 if ( $login_controller->login_allowed() ) {
149 if ($params->{grant_type} eq 'password' || !$params->{grant_type}) {
150 my $login_info = $login_controller->login_user( $params->{username}, $params->{password} );
151 if ($login_info->{account_disabled}) {
152 push(@status, 'Account Disabled');
154 if ($login_info->{incorrect_password}) {
155 push(@status, 'Incorrect Password');
157 if ($login_info->{duplicate_cookie_string}) {
158 push(@status, 'Duplicate Cookie String');
160 if ($login_info->{logins_disabled}) {
161 push(@status, 'Logins Disabled');
163 if ($login_info->{person_id}) {
164 push(@status, 'Login Successfull');
165 $cookie = $login_info->{cookie_string};
166 $first_name = $login_info->{first_name};
167 $last_name = $login_info->{last_name};
169 } else {
170 push(@status, 'Grant Type Not Supported. Valid grant type: password');
172 } else {
173 push(@status, 'Login Not Allowed');
175 my %pagination = ();
176 my @data_files;
177 my %metadata = (pagination=>\%pagination, status=>\@status, datafiles=>\@data_files);
178 my %response = (metadata=>\%metadata, access_token=>$cookie, userDisplayName=>"$first_name $last_name", expires_in=>$CXGN::Login::LOGIN_TIMEOUT);
179 $c->stash->{rest} = \%response;
183 =head2 /brapi/v1/calls
185 Usage: For determining which calls have been implemented and with which datafile types and methods
186 Desc:
188 GET Request:
190 GET Response:
192 "metadata": {
193 "pagination": {
194 "pageSize": 3,
195 "currentPage": 0,
196 "totalCount": 3,
197 "totalPages": 1
199 "status": {},
200 "datafiles": []
202 "result": {
203 "data": [
205 "call": "allelematrix",
206 "datatypes": [
207 "json",
208 "tsv"
210 "methods": [
211 "GET",
212 "POST"
216 "call": "germplasm/id/mcpd",
217 "datatypes": [
218 "json"
220 "methods": [
221 "GET"
225 "call": "doesntexistyet",
226 "datatypes": [
227 "png",
228 "jpg"
230 "methods": [
231 "GET"
238 =cut
240 sub calls : Chained('brapi') PathPart('calls') Args(0) : ActionClass('REST') { }
242 sub calls_GET {
243 my $self = shift;
244 my $c = shift;
246 my $status = $c->stash->{status};
247 my @status = @$status;
248 my @data;
249 push @data, {call=>'token', datatypes=>['json'], methods=>['POST','DELETE']};
250 push @data, {call=>'calls', datatypes=>['json'], methods=>['GET']};
252 my %pagination = ();
253 my %result = (data=>\@data);
254 my @data_files;
255 my %metadata = (pagination=>\%pagination, status=>\@status, datafiles=>\@data_files);
256 my %response = (metadata=>\%metadata, result=>\%result);
257 $c->stash->{rest} = \%response;
262 sub pagination_response {
263 my $data_count = shift;
264 my $page_size = shift;
265 my $page = shift;
266 my $total_pages_decimal = $data_count/$page_size;
267 my $total_pages = ($total_pages_decimal == int $total_pages_decimal) ? $total_pages_decimal : int($total_pages_decimal + 1);
268 my %pagination = (pageSize=>$page_size, currentPage=>$page, totalCount=>$data_count, totalPages=>$total_pages);
269 return \%pagination;
273 =head2 /brapi/v1/germplasm-search?germplasmName=&germplasmGenus=&germplasmSubTaxa=&germplasmDbId&germplasmPUI=http://data.inra.fr/accession/234Col342&germplasmSpecies=Triticum&panel=diversitypanel1&collection=none&pageSize=pageSize&page=page
275 Usage: For searching a germplasm by name. Allows for exact and wildcard match methods. http://docs.brapi.apiary.io/#germplasm
276 Desc:
278 POST Request:
281 "germplasmPUI" : "http://...", // (optional, text, `http://data.inra.fr/accession/234Col342`) ... The name or synonym of external genebank accession identifier
282 "germplasmDbId" : 986, // (optional, text, `986`) ... The name or synonym of external genebank accession identifier
283 "germplasmSpecies" : "tomato", // (optional, text, `aestivum`) ... The name or synonym of genus or species ( merge with below ?)
284 "germplasmGenus" : "Solanum lycopersicum", //(optional, text, `Triticum, Hordeum`) ... The name or synonym of genus or species
285 "germplasmName" : "XYZ1", // (optional, text, `Triticum, Hordeum`) ... The name or synonym of the accession
286 "accessionNumber" : "ITC1234" // optional
287 "pageSize" : 100, // (optional, integer, `1000`) ... The size of the pages to be returned. Default is `1000`.
288 "page": 1 (optional, integer, `10`) ... Which result page is requested
292 POST Response:
294 "metadata": {
295 "status": {},
296 "datafiles": [],
297 "pagination": {
298 "pageSize": 10,
299 "currentPage": 1,
300 "totalCount": 2,
301 "totalPages": 1
304 "result": {
305 "data":[
307 "germplasmDbId": "01BEL084609",
308 "defaultDisplayName": "Pahang",
309 "accessionNumber": "ITC0609",
310 "germplasmName": "Pahang",
311 "germplasmPUI": "http://www.crop-diversity.org/mgis/accession/01BEL084609",
312 "pedigree": "TOBA97/SW90.1057",
313 "germplasmSeedSource": "Female GID:4/Male GID:4",
314 "synonyms": [ ],
315 "commonCropName": "banana",
316 "instituteCode": "01BEL084",
317 "instituteName": "ITC",
318 "biologicalStatusOfAccessionCode": 412,
319 "countryOfOriginCode": "UNK",
320 "typeOfGermplasmStorageCode": 10,
321 "genus": "Musa",
322 "species": "acuminata",
323 "speciesAuthority": "",
324 "subtaxa": "sp malaccensis var pahang",
325 "subtaxaAuthority": "",
326 "donors":
329 "donorAccessionNumber": "",
330 "donorInstituteCode": "",
331 "germplasmPUI": ""
334 "acquisitionDate": "19470131"
340 =cut
342 sub germplasm_synonyms {
343 my $schema = shift;
344 my $stock_id = shift;
345 my $synonym_id = shift;
346 my @synonyms;
347 my $rsp = $schema->resultset("Stock::Stockprop")->search({type_id => $synonym_id, stock_id=>$stock_id });
348 while (my $stockprop = $rsp->next()) {
349 push( @synonyms, $stockprop->value() );
351 return \@synonyms;
354 sub germplasm_pedigree_string {
355 my $schema = shift;
356 my $stock_id = shift;
357 my $s = CXGN::Chado::Stock->new($schema, $stock_id);
358 my $pedigree_root = $s->get_parents('1');
359 my $pedigree_string = $pedigree_root->get_pedigree_string('1');
360 return $pedigree_string;
363 sub germplasm_list : Chained('brapi') PathPart('germplasm-search') Args(0) : ActionClass('REST') { }
365 #sub germplasm_list_POST {
366 # my $self = shift;
367 # my $c = shift;
368 # my $auth = _authenticate_user($c);
370 # my $status = $c->stash->{status};
371 # my @status = @$status;
373 # $c->stash->{rest} = {status => \@status};
376 sub germplasm_list_POST {
377 my $self = shift;
378 my $c = shift;
379 #my $auth = _authenticate_user($c);
380 my $params = $c->req->params();
382 my $status = $c->stash->{status};
383 my @status = @$status;
385 my $germplasm_name = $params->{germplasmName};
386 my $accession_number = $params->{accessionNumber};
387 my $genus = $params->{germplasmGenus};
388 my $subtaxa = $params->{germplasmSubTaxa};
389 my $species = $params->{germplasmSpecies};
390 my $germplasm_id = $params->{germplasmDbId};
391 my $permplasm_pui = $params->{germplasmPUI};
392 my $match_method = $params->{matchMethod};
393 if ($match_method && ($match_method ne 'exact' || $match_method ne 'wildcard')) {
394 push(@status, "matchMethod '$match_method' not recognized. Allowed matchMethods: wildcard, exact. Wildcard allows % or * for multiple characters and ? for single characters.");
397 my $total_count = 0;
398 my %result;
400 my $accession_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
401 my %search_params;
402 my %order_params;
403 my @select_list = ['me.stock_id', 'me.name', 'me.uniquename'];
404 my @sselect_as_list = ['stock_id', 'name', 'uniquename'];
406 $search_params{'me.type_id'} = $accession_type_cvterm_id;
407 $order_params{'-asc'} = 'me.stock_id';
409 if ($germplasm_name && (!$match_method || $match_method eq 'exact')) {
410 $search_params{'me.uniquename'} = $germplasm_name;
412 if ($germplasm_name && $match_method eq 'wildcard') {
413 $germplasm_name =~ tr/*?/%_/;
414 $search_params{'me.uniquename'} = { 'ilike' => $germplasm_name };
416 if ($germplasm_id && (!$match_method || $match_method eq 'exact')) {
417 $search_params{'me.stock_id'} = $germplasm_id;
419 if ($germplasm_id && $match_method eq 'wildcard') {
420 $germplasm_id =~ tr/*?/%_/;
421 $search_params{'me.stock_id'} = { 'ilike' => $germplasm_id };
423 #print STDERR Dumper \%search_params;
424 my $rs = $self->bcs_schema()->resultset("Stock::Stock")->search( \%search_params, { '+select'=> \@select_list, '+as'=> \@sselect_as_list, order_by=> \%order_params } );
425 my $synonym_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'stock_synonym', 'stock_property')->cvterm_id();
426 if ($accession_number) {
427 $search_params{'stockprops.type_id'} = $synonym_id;
428 $search_params{'stockprops.value'} = $accession_number;
429 $rs = $self->bcs_schema()->resultset("Stock::Stock")->search( \%search_params, { join=>{'stockprops'}, '+select'=> \@select_list, '+as'=> \@sselect_as_list, order_by=> \%order_params } );
432 my @data;
433 if ($rs) {
434 $total_count = $rs->count();
435 my $rs_slice = $rs->slice($c->stash->{page_size}*($c->stash->{current_page}-1), $c->stash->{page_size}*$c->stash->{current_page}-1);
436 while (my $stock = $rs_slice->next()) {
437 push @data, {
438 germplasmDbId=>$stock->get_column('stock_id'),
439 defaultDisplayName=>$stock->get_column('name'),
440 germplasmName=>$stock->get_column('uniquename'),
441 accessionNumber=>$accession_number,
442 germplasmPUI=>$stock->get_column('uniquename'),
443 pedigree=>germplasm_pedigree_string($self->bcs_schema(), $stock->get_column('stock_id')),
444 germplasmSeedSource=>'',
445 synonyms=>germplasm_synonyms($self->bcs_schema(), $stock->get_column('stock_id'), $synonym_id),
446 commonCropName=>'',
447 instituteCode=>'',
448 instituteName=>'',
449 biologicalStatusOfAccessionCode=>'',
450 countryOfOriginCode=>'',
451 typeOfGermplasmStorageCode=>'',
452 genus=>'',
453 species=>'',
454 speciesAuthority=>'',
455 subtaxa=>'',
456 subtaxaAuthority=>'',
457 donors=>'',
458 acquisitionDate=>'',
463 %result = (data => \@data);
464 my %metadata = (pagination=> pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
465 my %response = (metadata=>\%metadata, result=>\%result);
466 $c->stash->{rest} = \%response;
469 =head2 brapi/v1/germplasm/{id}
471 Usage: To retrieve details for a single germplasm
472 Desc:
473 Return JSON example:
475 "metadata": {
476 "status": [],
477 "pagination": {}
479 "result": {
480 "germplasmDbId": "01BEL084609",
481 "defaultDisplayName": "Pahang",
482 "germplasmName": "Pahang",
483 "accessionNumber": "ITC0609",
484 "germplasmPUI": "http://www.crop-diversity.org/mgis/accession/01BEL084609",
485 "pedigree": "TOBA97/SW90.1057",
486 "seedSource": "Female GID:4/Male GID:4",
487 "synonyms": ["Pahanga","Pahange"],
490 Args:
491 Side Effects:
493 =cut
495 sub germplasm_single : Chained('brapi') PathPart('germplasm') CaptureArgs(1) {
496 my $self = shift;
497 my $c = shift;
498 my $stock_id = shift;
500 $c->stash->{stock_id} = $stock_id;
501 $c->stash->{stock} = CXGN::Chado::Stock->new($self->bcs_schema(), $stock_id);
505 sub germplasm_detail : Chained('germplasm_single') PathPart('') Args(0) : ActionClass('REST') { }
507 sub germplasm_detail_POST {
508 my $self = shift;
509 my $c = shift;
510 my $auth = _authenticate_user($c);
511 my $status = $c->stash->{status};
512 my @status = @$status;
514 $c->stash->{rest} = {status=>\@status};
517 sub germplasm_detail_GET {
518 my $self = shift;
519 my $c = shift;
520 #my $auth = _authenticate_user($c);
521 my $rs = $c->stash->{stock};
522 my $schema = $self->bcs_schema();
523 my $status = $c->stash->{status};
524 my @status = @$status;
526 my $total_count = 0;
527 if ($c->stash->{stock}) {
528 $total_count = 1;
531 my %result;
532 my $synonym_id = $schema->resultset("Cv::Cvterm")->find( { name => "synonym" })->cvterm_id();
534 %result = (germplasmDbId=>$c->stash->{stock_id}, defaultDisplayName=>$c->stash->{stock}->get_name(), germplasmName=>$c->stash->{stock}->get_uniquename(), accessionNumber=>$c->stash->{stock}->get_uniquename(), germplasmPUI=>$c->stash->{stock}->get_uniquename(), pedigree=>germplasm_pedigree_string($self->bcs_schema(), $c->stash->{stock_id}), seedSource=>'', synonyms=>germplasm_synonyms($schema, $c->stash->{stock_id}, $synonym_id));
536 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
537 my %response = (metadata=>\%metadata, result=>\%result);
538 $c->stash->{rest} = \%response;
541 =head2 brapi/v1/germplasm/{id}/MCPD
543 Usage: To retrieve multi crop passport descriptor for a single germplasm
544 Desc:
545 Return JSON example:
547 "metadata": {
548 "status": [],
549 "pagination": {}
551 "result": {
552 "germplasmDbId": "01BEL084609",
553 "defaultDisplayName": "Pahang",
554 "accessionNumber": "ITC0609",
555 "germplasmName": "Pahang",
556 "germplasmPUI": "http://www.crop-diversity.org/mgis/accession/01BEL084609",
557 "pedigree": "TOBA97/SW90.1057",
558 "germplasmSeedSource": "Female GID:4/Male GID:4",
559 "synonyms": [ ],
560 "commonCropName": "banana",
561 "instituteCode": "01BEL084",
562 "instituteName": "ITC",
563 "biologicalStatusOfAccessionCode": 412,
564 "countryOfOriginCode": "UNK",
565 "typeOfGermplasmStorageCode": 10,
566 "genus": "Musa",
567 "species": "acuminata",
568 "speciesAuthority": "",
569 "subtaxa": "sp malaccensis var pahang",
570 "subtaxaAuthority": "",
571 "donors":
574 "donorAccessionNumber": "",
575 "donorInstituteCode": "",
576 "germplasmPUI": ""
579 "acquisitionDate": "19470131"
581 Args:
582 Side Effects:
584 =cut
586 sub germplasm_mcpd : Chained('germplasm_single') PathPart('MCPD') Args(0) : ActionClass('REST') { }
588 sub germplasm_mcpd_POST {
589 my $self = shift;
590 my $c = shift;
591 my $auth = _authenticate_user($c);
592 my $status = $c->stash->{status};
593 my @status = @$status;
595 $c->stash->{rest} = {status=>\@status};
598 sub germplasm_mcpd_GET {
599 my $self = shift;
600 my $c = shift;
601 #my $auth = _authenticate_user($c);
602 my $schema = $self->bcs_schema();
603 my %result;
604 my $status = $c->stash->{status};
605 my @status = @$status;
607 my $synonym_id = $schema->resultset("Cv::Cvterm")->find( { name => "synonym" })->cvterm_id();
608 my $organism = CXGN::Chado::Organism->new( $schema, $c->stash->{stock}->get_organism_id() );
610 %result = (germplasmDbId=>$c->stash->{stock_id}, defaultDisplayName=>$c->stash->{stock}->get_uniquename(), accessionNumber=>$c->stash->{stock}->get_uniquename(), germplasmName=>$c->stash->{stock}->get_name(), germplasmPUI=>$c->stash->{stock}->get_uniquename(), pedigree=>germplasm_pedigree_string($schema, $c->stash->{stock_id}), germplasmSeedSource=>'', synonyms=>germplasm_synonyms($schema, $c->stash->{stock_id}, $synonym_id), commonCropName=>$organism->get_common_name(), instituteCode=>'', instituteName=>'', biologicalStatusOfAccessionCode=>'', countryOfOriginCode=>'', typeOfGermplasmStorageCode=>'', genus=>$organism->get_genus(), species=>$organism->get_species(), speciesAuthority=>'', subtaxa=>$organism->get_taxon(), subtaxaAuthority=>'', donors=>'', acquisitionDate=>'');
612 my %pagination;
613 my %metadata = (pagination=>\%pagination, status=>\@status);
614 my %response = (metadata=>\%metadata, result=>\%result);
615 $c->stash->{rest} = \%response;
619 =head2 brapi/v1/studies?programId=programId
621 Usage: To retrieve studies
622 Desc:
623 Return JSON example:
625 "metadata": {
626 "pagination": {
627 "pageSize": 2,
628 "currentPage": 1,
629 "totalCount": 100,
630 "totalPages": 50
632 "status" : []
634 "result": {
635 "data": [
637 "studyDbId": 35,
638 "name": "Earlygenerationtesting",
639 "studyType": "Trial",
640 "years": ["2005", "2008"],
641 "locationDbId": 23,
642 "programDbId": 27,
643 "optionalInfo" : {
644 "studyPUI" : "PUI string",
645 "studyType": "Trial",
646 "startDate": "2015-06-01",
647 "endDate" : "2015-12-31",
652 "studyDbId": 345,
653 "name": "Earlygenerationtesting",
654 "seasons": ["2005", "2008"],
655 "locationDbId": 33,
656 "programDbId": 58,
657 "optionalInfo" : {
658 "studyPUI" : "PUI string",
659 "studyType": "Trial",
660 "startDate": "2015-06-01",
661 "endDate" : "2015-12-31",
667 Args:
668 Side Effects:
670 =cut
672 sub studies_list : Chained('brapi') PathPart('studies') Args(0) : ActionClass('REST') { }
674 sub studies_list_POST {
675 my $self = shift;
676 my $c = shift;
677 my $auth = _authenticate_user($c);
678 my $status = $c->stash->{status};
679 my @status = @$status;
681 my $study_name = $c->req->param('studyName');
682 my $location_id = $c->req->param('locationDbId');
683 my $years = $c->req->param('studyYears');
684 my $program_id = $c->req->param('programDbId');
685 my $optional_info = $c->req->param('optionalInfo');
687 my $description;
688 my $study_type;
689 if ($optional_info) {
690 my $opt_info_hash = decode_json($optional_info);
691 $description = $opt_info_hash->{"studyObjective"};
692 $study_type = $opt_info_hash->{"studyType"};
695 my $program_obj = CXGN::BreedersToolbox::Projects->new({schema => $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado') });
696 my $programs = $program_obj->get_breeding_programs();
697 my $program_check;
698 my $program_name;
699 foreach (@$programs) {
700 if ($_->[0] == $program_id) {
701 $program_check = 1;
702 $program_name = $_->[1];
705 if (!$program_check) {
706 push @status, "Program not found with programDbId = ".$program_id;
707 $c->stash->{rest} = {status => \@status };
708 return;
711 my $locations = $program_obj->get_all_locations();
712 my $location_check;
713 my $location_name;
714 foreach (@$locations) {
715 if ($_->[0] == $location_id) {
716 $location_check = 1;
717 $location_name = $_->[1];
720 if (!$location_check) {
721 push @status, "Location not found with locationDbId = ".$location_id;
722 $c->stash->{rest} = {status => \@status };
723 return;
726 my $trial_design;
727 my $trial_create = CXGN::Trial::TrialCreate->new({
728 dbh => $c->dbc->dbh,
729 chado_schema => $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado'),
730 metadata_schema => $c->dbic_schema("CXGN::Metadata::Schema"),
731 phenome_schema => $c->dbic_schema("CXGN::Phenome::Schema"),
732 user_name => $c->user()->get_object()->get_username(),
733 program => $program_name,
734 trial_year => $years,
735 trial_description => $description,
736 design_type => $study_type,
737 trial_location => $location_name,
738 trial_name => $study_name,
739 design => $trial_design,
742 if ($trial_create->trial_name_already_exists()) {
743 push @status, "Trial name \"".$trial_create->get_trial_name()."\" already exists.";
744 $c->stash->{rest} = {status => \@status };
745 return;
748 my $error;
750 try {
751 $trial_create->save_trial();
752 } catch {
753 push @status, "Error saving trial in the database $_";
754 $c->stash->{rest} = {status => \@status};
755 $error = 1;
757 if ($error) {
758 return;
761 push @status, "Study saved successfully.";
762 $c->stash->{rest} = {status => \@status};
765 sub studies_list_GET {
766 my $self = shift;
767 my $c = shift;
768 #my $auth = _authenticate_user($c);
769 my $program_id = $c->req->param("programId");
770 my $status = $c->stash->{status};
771 my @status = @$status;
773 my @data;
774 my %result;
775 my $rs;
776 if (!$program_id) {
777 $rs = $self->bcs_schema->resultset('Project::Project')->search(
778 {'type.name' => 'breeding_program_trial_relationship' },
779 {join=> {'project_relationship_subject_projects' => 'type'},
780 '+select'=> ['me.project_id'],
781 '+as'=> ['study_id' ],
782 order_by=>{ -asc=>'me.project_id' }
785 }elsif ($program_id) {
786 $rs = $self->bcs_schema->resultset('Project::Project')->search(
787 {'type.name' => 'breeding_program_trial_relationship', 'project_relationship_subject_projects.object_project_id' => $program_id },
788 {join=> {'project_relationship_subject_projects' => 'type'},
789 '+select'=> ['me.project_id'],
790 '+as'=> ['study_id' ],
791 order_by=>{ -asc=>'me.project_id' }
796 my $total_count = 0;
797 if ($rs) {
798 $total_count = $rs->count();
799 my $rs_slice = $rs->slice($c->stash->{page_size}*($c->stash->{current_page}-1), $c->stash->{page_size}*$c->stash->{current_page}-1);
800 while (my $s = $rs_slice->next()) {
801 my $t = CXGN::Trial->new( { trial_id => $s->get_column('study_id'), bcs_schema => $self->bcs_schema } );
803 my @years = ($t->get_year());
804 my %optional_info = (studyPUI=>'', startDate => $t->get_planting_date(), endDate => $t->get_harvest_date());
805 my $project_type = '';
806 if ($t->get_project_type()) {
807 $project_type = $t->get_project_type()->[1];
809 my $location = '';
810 if ($t->get_location()) {
811 $location = $t->get_location()->[0];
813 push @data, {studyDbId=>$t->get_trial_id(), name=>$t->get_name(), studyType=>$project_type, years=>\@years, locationDbId=>$location, optionalInfo=>\%optional_info};
817 %result = (data=>\@data);
818 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
819 my %response = (metadata=>\%metadata, result=>\%result);
820 $c->stash->{rest} = \%response;
823 =head2 brapi/v1/studies/{studyId}/germplasm?pageSize=20&page=1
825 Usage: To retrieve all germplasm used in a study
826 Desc:
827 Return JSON example:
829 "metadata": {
830 "status": [],
831 "pagination": {
832 "pageSize": 1000,
833 "currentPage": 1,
834 "totalCount": 1,
835 "totalPages": 1
838 "result": {
839 "studyDbId": 123,
840 "studyName": "myBestTrial",
841 "data": [
843 "germplasmDbId": "382",
844 "trialEntryNumberId": "1",
845 "defaultDisplayName": "Pahang",
846 "germplasmName": "Pahang",
847 "accessionNumber": "ITC0609",
848 "germplasmPUI": "http://www.crop-diversity.org/mgis/accession/01BEL084609",
849 "pedigree": "TOBA97/SW90.1057",
850 "seedSource": "",
851 "synonyms": ["01BEL084609"],
854 "germplasmDbId": "394",
855 "trialEntryNumberId": "2",
856 "defaultDisplayName": "Pahang",
857 "germplasmName": "Pahang",
858 "accessionNumber": "ITC0727",
859 "germplasmPUI": "http://www.crop-diversity.org/mgis/accession/01BEL084727",
860 "pedigree": "TOBA97/SW90.1057",
861 "seedSource": "",
862 "synonyms": [ "01BEL084727"],
867 Args:
868 Side Effects:
870 =cut
872 sub studies_single : Chained('brapi') PathPart('studies') CaptureArgs(1) {
873 my $self = shift;
874 my $c = shift;
875 my $study_id = shift;
877 $c->stash->{study_id} = $study_id;
878 my $t = CXGN::Trial->new( { trial_id => $study_id, bcs_schema => $self->bcs_schema } );
879 $c->stash->{study} = $t;
880 $c->stash->{studyName} = $t->get_name();
884 sub studies_germplasm : Chained('studies_single') PathPart('germplasm') Args(0) : ActionClass('REST') { }
886 sub studies_germplasm_POST {
887 my $self = shift;
888 my $c = shift;
889 my $auth = _authenticate_user($c);
890 my $status = $c->stash->{status};
891 my @status = @$status;
893 my $metadata = $c->req->params("metadata");
894 my $result = $c->req->params("result");
895 my %metadata_hash = %$metadata;
896 my %result_hash = %$result;
898 print STDERR Dumper($metadata);
899 print STDERR Dumper($result);
901 my $pagintation = $metadata_hash{"pagination"};
902 push(@status, $metadata_hash{"status"});
904 $c->stash->{rest} = {status=>\@status};
907 sub studies_germplasm_GET {
908 my $self = shift;
909 my $c = shift;
910 #my $auth = _authenticate_user($c);
911 my %result;
912 my $status = $c->stash->{status};
913 my @status = @$status;
914 my $total_count = 0;
916 my $synonym_id = $self->bcs_schema->resultset("Cv::Cvterm")->find( { name => "synonym" })->cvterm_id();
917 my $tl = CXGN::Trial::TrialLayout->new( { schema => $self->bcs_schema, trial_id => $c->stash->{study_id} });
918 my ($accessions, $controls) = $tl->_get_trial_accession_names_and_control_names();
919 my @germplasm_data;
921 if ($accessions) {
922 push (@$accessions, @$controls);
923 $total_count = scalar(@$accessions);
924 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
925 my $end = $c->stash->{page_size}*$c->stash->{current_page}-1;
926 for( my $i = $start; $i <= $end; $i++ ) {
927 if (@$accessions[$i]) {
928 push @germplasm_data, { germplasmDbId=>@$accessions[$i]->{stock_id}, germplasmName=>@$accessions[$i]->{accession_name}, studyEntryNumberId=>'', defaultDisplayName=>@$accessions[$i]->{accession_name}, accessionNumber=>@$accessions[$i]->{accession_name}, germplasmPUI=>@$accessions[$i]->{accession_name}, pedigree=>germplasm_pedigree_string($self->bcs_schema, @$accessions[$i]->{stock_id}), seedSource=>'', synonyms=>germplasm_synonyms($self->bcs_schema, @$accessions[$i]->{stock_id}, $synonym_id)};
933 %result = (studyDbId=>$c->stash->{study_id}, studyName=>$c->stash->{studyName}, data =>\@germplasm_data);
935 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
936 my %response = (metadata=>\%metadata, result=>\%result);
937 $c->stash->{rest} = \%response;
941 =head2 brapi/v1/germplasm/{id}/pedigree?notation=purdy
943 Usage: To retrieve pedigree information for a single germplasm
944 Desc:
945 Return JSON example:
947 "metadata": {
948 "status": [],
949 "pagination": {}
951 "result": {
952 "germplasmDbId": "382",
953 "pedigree": "TOBA97/SW90.1057",
954 "parent1Id": "23",
955 "parent2Id": "55"
958 Args:
959 Side Effects:
961 =cut
963 sub germplasm_pedigree : Chained('germplasm_single') PathPart('pedigree') Args(0) : ActionClass('REST') { }
965 sub germplasm_pedigree_POST {
966 my $self = shift;
967 my $c = shift;
968 my $auth = _authenticate_user($c);
969 my $status = $c->stash->{status};
970 my @status = @$status;
972 $c->stash->{rest} = {status=>\@status};
975 sub germplasm_pedigree_GET {
976 my $self = shift;
977 my $c = shift;
978 #my $auth = _authenticate_user($c);
979 my $schema = $self->bcs_schema();
980 my %result;
981 my $status = $c->stash->{status};
982 my @status = @$status;
983 my $total_count = 0;
985 if ($c->req->param('notation')) {
986 push @status, 'notation not implemented';
987 if ($c->req->param('notation') ne 'purdy') {
988 push @status, {code=>'ERR-1', message=>'Unsupported notation code.'};
992 my $s = $c->stash->{stock};
993 if ($s) {
994 $total_count = 1;
997 my @direct_parents = $s->get_direct_parents();
999 %result = (germplasmDbId=>$c->stash->{stock_id}, pedigree=>germplasm_pedigree_string($schema, $c->stash->{stock_id}), parent1Id=>$direct_parents[0][0], parent2Id=>$direct_parents[1][0]);
1001 my %pagination;
1002 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1003 my %response = (metadata=>\%metadata, result=>\%result);
1004 $c->stash->{rest} = \%response;
1007 =head2 brapi/v1/germplasm/{id}/markerprofiles
1009 Usage: To retrieve markerprofile ids for a single germplasm
1010 Desc:
1011 Return JSON example:
1013 "metadata": {
1014 "status": [],
1015 "pagination": {}
1017 "result": {
1018 "germplasmDbId": "382",
1019 "markerProfiles": [
1020 "123",
1021 "456"
1025 Args:
1026 Side Effects:
1028 =cut
1030 sub germplasm_markerprofile : Chained('germplasm_single') PathPart('markerprofiles') Args(0) : ActionClass('REST') { }
1032 sub germplasm_markerprofile_POST {
1033 my $self = shift;
1034 my $c = shift;
1035 my $auth = _authenticate_user($c);
1036 my $status = $c->stash->{status};
1037 my @status = @$status;
1039 $c->stash->{rest} = {status=>\@status};
1042 sub germplasm_markerprofile_GET {
1043 my $self = shift;
1044 my $c = shift;
1045 #my $auth = _authenticate_user($c);
1046 my $schema = $self->bcs_schema();
1047 my %result;
1048 my $status = $c->stash->{status};
1049 my @status = @$status;
1050 my @marker_profiles;
1052 my $snp_genotyping_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'snp genotyping', 'genotype_property')->cvterm_id();
1054 my $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
1055 {'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'stock.stock_id'=>$c->stash->{stock_id}},
1056 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
1057 select=> ['genotypeprops.genotypeprop_id'],
1058 as=> ['genotypeprop_id'],
1059 order_by=>{ -asc=>'genotypeprops.genotypeprop_id' }
1063 my $rs_slice = $rs->slice($c->stash->{page_size}*($c->stash->{current_page}-1), $c->stash->{page_size}*$c->stash->{current_page}-1);
1064 while (my $gt = $rs_slice->next()) {
1065 push @marker_profiles, $gt->get_column('genotypeprop_id');
1067 %result = (germplasmDbId=>$c->stash->{stock_id}, markerProfiles=>\@marker_profiles);
1068 my $total_count = scalar(@marker_profiles);
1069 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1070 my %response = (metadata=>\%metadata, result=>\%result);
1071 $c->stash->{rest} = \%response;
1076 # Need to implement Germplasm Attributes
1080 =head2 brapi/v1/markerprofiles?germplasm=germplasmDbId&extract=extractDbId&method=methodDbId
1082 Usage: To retrieve markerprofile ids for a single germplasm
1083 Desc:
1084 Return JSON example:
1086 "metadata" : {
1087 "pagination": {
1088 "pageSize": 10,
1089 "currentPage": 1,
1090 "totalCount": 10,
1091 "totalPages": 1
1093 "status": []
1095 "result" : {
1096 "data" : [
1098 "markerProfileDbId": "993",
1099 "germplasmDbId" : 2374,
1100 "extractDbId" : 3939,
1101 "analysisMethod": "GoldenGate",
1102 "resultCount": 1470
1105 "markerProfileDbId": "994",
1106 "germplasmDbId" : 2374,
1107 "extractDbId" : 3939,
1108 "analysisMethod": "GBS",
1109 "resultCount": 1470
1114 Args:
1115 Side Effects:
1117 =cut
1119 sub markerprofiles_list : Chained('brapi') PathPart('markerprofiles') Args(0) : ActionClass('REST') { }
1121 sub markerprofiles_list_POST {
1122 my $self = shift;
1123 my $c = shift;
1124 my $auth = _authenticate_user($c);
1125 my $status = $c->stash->{status};
1126 my @status = @$status;
1128 $c->stash->{rest} = {status=>\@status};
1131 sub markerprofiles_list_GET {
1132 my $self = shift;
1133 my $c = shift;
1134 #my $auth = _authenticate_user($c);
1135 my $germplasm = $c->req->param("germplasm");
1136 my $extract = $c->req->param("extract");
1137 my $method = $c->req->param("method");
1138 my $status = $c->stash->{status};
1139 my @status = @$status;
1140 my @data;
1141 my %result;
1143 my $snp_genotyping_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'snp genotyping', 'genotype_property')->cvterm_id();
1145 my $rs;
1146 if ($germplasm && $method) {
1147 $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
1148 {'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'stock.stock_id'=>$germplasm, 'nd_protocol.nd_protocol_id'=>$method},
1149 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
1150 select=> ['genotypeprops.genotypeprop_id', 'genotypeprops.value', 'nd_protocol.name', 'stock.stock_id'],
1151 as=> ['genotypeprop_id', 'value', 'protocol_name', 'stock_id'],
1152 order_by=>{ -asc=>'genotypeprops.genotypeprop_id' }
1156 if ($germplasm && !$method) {
1157 $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
1158 {'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'stock.stock_id'=>$germplasm},
1159 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
1160 select=> ['genotypeprops.genotypeprop_id', 'genotypeprops.value', 'nd_protocol.name', 'stock.stock_id'],
1161 as=> ['genotypeprop_id', 'value', 'protocol_name', 'stock_id'],
1162 order_by=>{ -asc=>'genotypeprops.genotypeprop_id' }
1166 if (!$germplasm && $method) {
1167 $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
1168 {'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'nd_protocol.nd_protocol_id'=>$method},
1169 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
1170 select=> ['genotypeprops.genotypeprop_id', 'genotypeprops.value', 'nd_protocol.name', 'stock.stock_id'],
1171 as=> ['genotypeprop_id', 'value', 'protocol_name', 'stock_id'],
1172 order_by=>{ -asc=>'genotypeprops.genotypeprop_id' }
1176 if (!$germplasm && !$method) {
1177 $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
1178 { 'genotypeprops.type_id' => $snp_genotyping_cvterm_id },
1179 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
1180 select=> ['genotypeprops.genotypeprop_id', 'genotypeprops.value', 'nd_protocol.name', 'stock.stock_id'],
1181 as=> ['genotypeprop_id', 'value', 'protocol_name', 'stock_id'],
1182 order_by=>{ -asc=>'genotypeprops.genotypeprop_id' }
1187 if ($extract) {
1188 push @status, 'Extract not supported';
1191 if ($rs) {
1192 my $rs_slice = $rs->slice($c->stash->{page_size}*($c->stash->{current_page}-1), $c->stash->{page_size}*$c->stash->{current_page}-1);
1193 while (my $row = $rs_slice->next()) {
1194 my $genotype_json = $row->get_column('value');
1195 my $genotype = JSON::Any->decode($genotype_json);
1197 push @data, {markerProfileDbId => $row->get_column('genotypeprop_id'), germplasmDbId => $row->get_column('stock_id'), extractDbId => "", analysisMethod => $row->get_column('protocol_name'), resultCount => scalar(keys(%$genotype)) };
1201 my $total_count = $rs->count();
1203 %result = (data => \@data);
1204 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1205 my %response = (metadata=>\%metadata, result=>\%result);
1206 $c->stash->{rest} = \%response;
1210 =head2 brapi/v1/markerprofiles/markerprofilesDbId
1212 Usage: To retrieve data for a single markerprofile
1213 Desc:
1214 Return JSON example:
1216 "metadata" : {
1217 "pagination": {
1218 "pageSize": 10,
1219 "currentPage": 1,
1220 "totalCount": 10,
1221 "totalPages": 1
1223 "status": []
1226 "result": {
1227 "germplasmDbId": 993,
1228 "extractDbId" : 38383,
1229 "markerprofileDbId": 37484,
1230 "analysisMethod": "GBS-Pst1",
1231 "encoding": "AA,BB,AB",
1232 "data" : [ { "marker1": "AA" }, { "marker2":"AB" }, ... ]
1235 Args:
1236 Side Effects:
1238 =cut
1240 sub markerprofiles_single : Chained('brapi') PathPart('markerprofiles') CaptureArgs(1) {
1241 my $self = shift;
1242 my $c = shift;
1243 my $id = shift;
1244 $c->stash->{markerprofile_id} = $id; # this is genotypeprop_id
1247 sub genotype_fetch : Chained('markerprofiles_single') PathPart('') Args(0) : ActionClass('REST') { }
1249 sub genotype_fetch_POST {
1250 my $self = shift;
1251 my $c = shift;
1252 my $auth = _authenticate_user($c);
1253 my $status = $c->stash->{status};
1254 my @status = @$status;
1256 $c->stash->{rest} = {status=>\@status};
1259 sub genotype_fetch_GET {
1260 my $self = shift;
1261 my $c = shift;
1262 #my $auth = _authenticate_user($c);
1263 my $status = $c->stash->{status};
1264 my @status = @$status;
1265 my @data;
1266 my %result;
1268 my $total_count = 0;
1269 my $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->find(
1270 {'genotypeprops.genotypeprop_id' => $c->stash->{markerprofile_id} },
1271 {join=> [{'nd_experiment_genotypes' => {'genotype' => 'genotypeprops'} }, {'nd_experiment_protocols' => 'nd_protocol' }, {'nd_experiment_stocks' => 'stock'} ],
1272 select=> ['genotypeprops.value', 'nd_protocol.name', 'stock.stock_id'],
1273 as=> ['value', 'protocol_name', 'stock_id'],
1277 if ($rs) {
1278 my $genotype_json = $rs->get_column('value');
1279 my $genotype = JSON::Any->decode($genotype_json);
1280 $total_count = scalar keys %$genotype;
1282 foreach my $m (sort genosort keys %$genotype) {
1283 push @data, { $m=>$self->convert_dosage_to_genotype($genotype->{$m}) };
1286 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
1287 my $end = $c->stash->{page_size}*$c->stash->{current_page};
1288 my @data_window = splice @data, $start, $end;
1290 %result = (germplasmDbId=>$rs->get_column('stock_id'), extractDbId=>'', markerprofileDbId=>$c->stash->{markerprofile_id}, analysisMethod=>$rs->get_column('protocol_name'), encoding=>"AA,BB,AB", data => \@data_window);
1293 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1294 my %response = (metadata=>\%metadata, result=>\%result);
1295 $c->stash->{rest} = \%response;
1299 sub markerprofiles_methods : Chained('brapi') PathPart('markerprofiles/methods') Args(0) {
1300 my $self = shift;
1301 my $c = shift;
1302 #my $auth = _authenticate_user($c);
1303 my $status = $c->stash->{status};
1304 my @status = @$status;
1306 my $rs = $self->bcs_schema()->resultset("NaturalDiversity::NdProtocol")->search( { } );
1307 my @response;
1308 while (my $row = $rs->next()) {
1309 push @response, [ $row->nd_protocol_id(), $row->name() ];
1311 $c->stash->{rest} = \@response;
1316 sub genosort {
1317 my ($a_chr, $a_pos, $b_chr, $b_pos);
1318 if ($a =~ m/S(\d+)\_(.*)/) {
1319 $a_chr = $1;
1320 $a_pos = $2;
1322 if ($b =~ m/S(\d+)\_(.*)/) {
1323 $b_chr = $1;
1324 $b_pos = $2;
1327 if ($a_chr && $b_chr) {
1328 if ($a_chr == $b_chr) {
1329 return $a_pos <=> $b_pos;
1331 return $a_chr <=> $b_chr;
1332 } else {
1333 return -1;
1338 sub convert_dosage_to_genotype {
1339 my $self = shift;
1340 my $dosage = shift;
1342 my $genotype;
1343 if ($dosage eq "NA") {
1344 return "NA";
1346 if ($dosage == 1) {
1347 return "AA";
1349 elsif ($dosage == 0) {
1350 return "BB";
1352 elsif ($dosage == 2) {
1353 return "AB";
1355 else {
1356 return "NA";
1361 =head2 brapi/v1/allelematrix?markerprofileDbId=100&markerprofileDbId=101
1363 Usage: Gives a matrix data structure for a given list of markerprofileDbIds
1364 Desc:
1365 Return JSON example:
1367 "metadata": {
1368 "status": [],
1369 "pagination": {
1370 "pageSize": 100,
1371 "currentPage": 1,
1372 "totalCount": 1,
1373 "totalPages": 1
1376 "result" : {
1377 "makerprofileDbIds": ["markerprofileId1","markerprofileId2","markerprofileId3"],
1378 "data" : [
1379 { "markerId1":["AB","AA","AA"] },
1380 { "markerId2":["AA","AB","AA"] },
1381 { "markerId3":["AB","AB","BB"] }
1385 Args:
1386 Side Effects:
1388 =cut
1390 sub allelematrix : Chained('brapi') PathPart('allelematrix') Args(0) {
1391 my $self = shift;
1392 my $c = shift;
1393 #my $auth = _authenticate_user($c);
1394 my $status = $c->stash->{status};
1395 my @status = @$status;
1397 my @profile_ids = $c->req->param('markerprofileDbId');
1398 my $data_format = $c->req->param('format');
1399 #print STDERR Dumper \@profile_ids;
1400 #my @profile_ids = split ",", $markerprofile_ids;
1402 my $rs = $self->bcs_schema()->resultset("Genetic::Genotypeprop")->search( { genotypeprop_id => { -in => \@profile_ids }});
1404 my %scores;
1405 my $total_pages;
1406 my $total_count;
1407 my @marker_score_lines;
1408 my @ordered_refmarkers;
1409 my $markers;
1410 if ($rs->count() > 0) {
1411 while (my $profile = $rs->next()) {
1412 my $profile_json = $profile->value();
1413 my $refmarkers = JSON::Any->decode($profile_json);
1414 #print STDERR Dumper($refmarkers);
1415 push @ordered_refmarkers, sort genosort keys(%$refmarkers);
1418 #print Dumper(\@ordered_refmarkers);
1420 my $json = JSON->new();
1421 $rs = $self->bcs_schema()->resultset("Genetic::Genotypeprop")->search( { genotypeprop_id => { -in => \@profile_ids }});
1422 while (my $profile = $rs->next()) {
1423 foreach my $m (@ordered_refmarkers) {
1424 my $markers_json = $profile->value();
1425 $markers = $json->decode($markers_json);
1427 $scores{$profile->genotypeprop_id()}->{$m} = $self->convert_dosage_to_genotype($markers->{$m});
1432 #print STDERR Dumper \%scores;
1434 my @lines;
1435 foreach my $line (keys %scores) {
1436 push @lines, $line;
1439 my @json_lines;
1440 my $fh;
1441 my $file_path;
1442 my %markers_seen;
1443 my $data_file_path;
1444 my @marker_score_json_lines;
1445 if (!$data_format || $data_format eq 'json' ){
1446 @json_lines = @lines;
1447 print STDERR scalar(@ordered_refmarkers)."\n";
1449 for (my $n = $c->stash->{page_size} * ($c->stash->{current_page}-1); $n< ($c->stash->{page_size} * ($c->stash->{current_page})); $n++) {
1451 my %markers_by_line;
1452 my $m = $ordered_refmarkers[$n];
1453 #print STDERR Dumper $m;
1454 foreach my $line (keys %scores) {
1455 push @{$markers_by_line{$m}}, $scores{$line}->{$m};
1456 if (!exists $markers_seen{$m} ) {
1457 #print STDERR Dumper \@{$markers_by_line{$m}};
1458 $markers_seen{$m} = \@{$markers_by_line{$m}};
1459 #push @marker_score_lines, { $m => \@{$markers_by_line{$m}} };
1464 foreach my $marker_name (sort keys %markers_seen) {
1465 my $marker_scores = $markers_seen{$marker_name};
1466 #print STDERR Dumper $marker_scores;
1467 push @marker_score_json_lines, { $marker_name => $marker_scores };
1471 } elsif ($data_format eq 'tsv') {
1472 my $dir = $c->tempfiles_subdir('download');
1473 my ($fh, $tempfile) = $c->tempfile( TEMPLATE => 'download/allelematrix_'.$data_format.'_'.'XXXXX');
1474 $file_path = $c->config->{basepath}."/".$tempfile.".tsv";
1475 open(my $fh, ">", $file_path);
1476 print STDERR $file_path."\n";
1477 print $fh "markerprofileDbIds\t", join("\t", @lines), "\n";
1479 my %markers_by_line;
1480 print STDERR scalar(@ordered_refmarkers)."\n";
1481 foreach my $m (@ordered_refmarkers) {
1482 #print STDERR Dumper $m;
1483 foreach my $line (keys %scores) {
1484 push @{$markers_by_line{$m}}, $scores{$line}->{$m};
1485 if (!exists $markers_seen{$m} ) {
1486 #print STDERR Dumper \@{$markers_by_line{$m}};
1487 $markers_seen{$m} = \@{$markers_by_line{$m}};
1488 #push @marker_score_lines, { $m => \@{$markers_by_line{$m}} };
1493 foreach my $marker_name (sort keys %markers_seen) {
1494 my $marker_scores = $markers_seen{$marker_name};
1495 #print STDERR Dumper $marker_scores;
1496 print $fh "$marker_name\t", join("\t", @{$marker_scores}),"\n";
1500 close $fh;
1501 $data_file_path = $file_path;
1506 $total_count = scalar(keys %$markers);
1508 $c->stash->{rest} = {
1509 metadata => { pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status => \@status, datafiles=>$data_file_path },
1510 result => {markerprofileDbIds => \@json_lines, data => \@marker_score_json_lines},
1516 =head2 brapi/v1/programs
1518 Usage: To retrieve a list of programs being worked on
1519 Desc:
1520 Return JSON example:
1522 "metadata" : {
1523 "pagination": {
1524 "pageSize": 10,
1525 "currentPage": 1,
1526 "totalCount": 10,
1527 "totalPages": 1
1529 "status": []
1531 "result" : {
1532 "data" : [
1534 "programDbid": "123",
1535 "name": "Wheat Resistance Program",
1536 "objective" : "Disease resistance",
1537 "leadPerson" : "Dr. Henry Beachell"
1540 "programDbId": "456",
1541 "name": "Wheat Improvement Program",
1542 "objective" : "Yield improvement",
1543 "leadPerson" : "Dr. Norman Borlaug"
1548 Args:
1549 Side Effects:
1551 =cut
1553 sub programs_list : Chained('brapi') PathPart('programs') Args(0) : ActionClass('REST') { }
1555 sub programs_list_POST {
1556 my $self = shift;
1557 my $c = shift;
1558 my $auth = _authenticate_user($c);
1559 my $status = $c->stash->{status};
1560 my @status = @$status;
1562 $c->stash->{rest} = {status=>\@status};
1565 sub programs_list_GET {
1566 my $self = shift;
1567 my $c = shift;
1568 #my $auth = _authenticate_user($c);
1569 my $status = $c->stash->{status};
1570 my @status = @$status;
1571 my %result;
1572 my @data;
1574 my $ps = CXGN::BreedersToolbox::Projects->new( { schema => $c->dbic_schema("Bio::Chado::Schema") });
1576 my $programs = $ps -> get_breeding_programs();
1577 my $total_count = scalar(@$programs);
1579 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
1580 my $end = $c->stash->{page_size}*$c->stash->{current_page}-1;
1581 for( my $i = $start; $i <= $end; $i++ ) {
1582 if (@$programs[$i]) {
1583 push @data, {programDbId=>@$programs[$i]->[0], name=>@$programs[$i]->[1], objective=>@$programs[$i]->[2], leadPerson=>''};
1587 %result = (data=>\@data);
1588 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1589 my %response = (metadata=>\%metadata, result=>\%result);
1590 $c->stash->{rest} = \%response;
1594 =head2 brapi/v1/studyTypes
1596 Usage: To retrieve a list of programs being worked onthe various study types
1597 Desc:
1598 Return JSON example:
1600 "metadata" : {
1601 "pagination": {
1602 "pageSize": 10,
1603 "currentPage": 1,
1604 "totalCount": 10,
1605 "totalPages": 1
1607 "status": []
1609 "result" : {
1610 "data" : [
1612 "name": "Nursery",
1613 "description": "Description for Nursery study type"
1616 "name": "Trial",
1617 "description": "Description for Nursery study type"
1622 Args:
1623 Side Effects:
1625 =cut
1627 sub studies_types_list : Chained('brapi') PathPart('studyTypes') Args(0) : ActionClass('REST') { }
1629 sub studies_types_list_POST {
1630 my $self = shift;
1631 my $c = shift;
1632 my $auth = _authenticate_user($c);
1633 my $status = $c->stash->{status};
1634 my @status = @$status;
1636 $c->stash->{rest} = {status=>\@status};
1639 sub studies_types_list_GET {
1640 my $self = shift;
1641 my $c = shift;
1642 #my $auth = _authenticate_user($c);
1643 my %result;
1644 my @data;
1645 my $status = $c->stash->{status};
1646 my @status = @$status;
1648 my @cvterm_ids = CXGN::Trial::get_all_project_types($self->bcs_schema);
1649 my $cvterm;
1650 foreach (@cvterm_ids) {
1651 $cvterm = CXGN::Chado::Cvterm->new($c->dbc->dbh, $_->[0]);
1652 push @data, {name=>$_->[1], description=>$cvterm->get_definition },
1655 my $total_count = scalar(@cvterm_ids);
1656 %result = (data => \@data);
1657 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1658 my %response = (metadata=>\%metadata, result=>\%result);
1659 $c->stash->{rest} = \%response;
1663 sub studies_instances : Chained('studies_single') PathPart('instances') Args(0) : ActionClass('REST') { }
1665 sub studies_instances_POST {
1666 my $self = shift;
1667 my $c = shift;
1668 my $auth = _authenticate_user($c);
1669 my $status = $c->stash->{status};
1670 my @status = @$status;
1672 $c->stash->{rest} = {status=>\@status};
1675 sub studies_instances_GET {
1676 my $self = shift;
1677 my $c = shift;
1678 #my $auth = _authenticate_user($c);
1679 my %result;
1680 my $status = $c->stash->{status};
1681 my @status = @$status;
1682 my $total_count = 0;
1684 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1685 my %response = (metadata=>\%metadata, result=>\%result);
1686 $c->stash->{rest} = \%response;
1690 sub studies_info : Chained('studies_single') PathPart('') Args(0) : ActionClass('REST') { }
1692 sub studies_info_POST {
1693 my $self = shift;
1694 my $c = shift;
1695 my $auth = _authenticate_user($c);
1696 my $status = $c->stash->{status};
1697 my @status = @$status;
1699 $c->stash->{rest} = {status => \@status};
1702 sub studies_info_GET {
1703 my $self = shift;
1704 my $c = shift;
1705 #my $auth = _authenticate_user($c);
1706 my %result;
1707 my $status = $c->stash->{status};
1708 my @status = @$status;
1709 my $total_count = 0;
1711 my $t = $c->stash->{study};
1712 if ($t) {
1713 $total_count = 1;
1714 my @years = ($t->get_year());
1715 my %optional_info = (studyPUI=>'', startDate=>'', endDate=>'');
1716 my $project_type = '';
1717 if ($t->get_project_type()) {
1718 $project_type = $t->get_project_type()->[1];
1720 my $location = '';
1721 if ($t->get_location()) {
1722 $location = $t->get_location()->[0];
1724 my $ps = CXGN::BreedersToolbox::Projects->new( { schema => $self->bcs_schema });
1725 my $programs = $ps->get_breeding_program_with_trial($c->stash->{study_id});
1727 %result = (studyDbId=>$t->get_trial_id(), studyName=>$t->get_name(), studyType=>$project_type, years=>\@years, locationDbId=>$location, programDbId=>@$programs[0]->[0], programName=>@$programs[0]->[1], optionalInfo=>\%optional_info);
1728 } else {
1729 push @status, "Study ID not found.";
1732 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1733 my %response = (metadata=>\%metadata, result=>\%result);
1734 $c->stash->{rest} = \%response;
1738 sub studies_details : Chained('studies_single') PathPart('details') Args(0) : ActionClass('REST') { }
1740 sub studies_details_POST {
1741 my $self = shift;
1742 my $c = shift;
1743 my $auth = _authenticate_user($c);
1744 my $status = $c->stash->{status};
1745 my @status = @$status;
1747 $c->stash->{rest} = {status => \@status};
1750 sub studies_details_GET {
1751 my $self = shift;
1752 my $c = shift;
1753 #my $auth = _authenticate_user($c);
1754 my $status = $c->stash->{status};
1755 my @status = @$status;
1756 my %result;
1757 my $total_count = 0;
1759 my $schema = $self->bcs_schema();
1760 my $t = $c->stash->{study};
1761 my $tl = CXGN::Trial::TrialLayout->new( { schema => $schema, trial_id => $c->stash->{study_id} });
1763 if ($t) {
1764 $total_count = 1;
1765 my ($accessions, $controls) = $tl->_get_trial_accession_names_and_control_names();
1766 my @germplasm_data;
1767 foreach (@$accessions) {
1768 push @germplasm_data, { germplasmDbId=>$_->{stock_id}, germplasmName=>$_->{accession_name}, germplasmPUI=>$_->{accession_name} };
1770 foreach (@$controls) {
1771 push @germplasm_data, { germplasmDbId=>$_->{stock_id}, germplasmName=>$_->{accession_name}, germplasmPUI=>$_->{accession_name} };
1774 my $ps = CXGN::BreedersToolbox::Projects->new( { schema => $self->bcs_schema });
1775 my $programs = $ps->get_breeding_program_with_trial($c->stash->{study_id});
1777 %result = (
1778 studyDbId => $c->stash->{study_id},
1779 studyId => $t->get_name(),
1780 studyPUI => "",
1781 studyName => $t->get_name(),
1782 studyObjective => $t->get_description(),
1783 studyType => $t->get_project_type() ? $t->get_project_type()->[1] : "trial",
1784 studyLocation => $t->get_location() ? $t->get_location()->[1] : undef,
1785 studyProject => $t->get_breeding_program(),
1786 dataSet => "",
1787 studyPlatform => "",
1788 startDate => $t->get_planting_date(),
1789 endDate => $t->get_harvest_date(),
1790 programDbId=>@$programs[0]->[0],
1791 programName=>@$programs[0]->[1],
1792 designType => $tl->get_design_type(),
1793 keyContact => "",
1794 contacts => "",
1795 meteoStationCode => "",
1796 meteoStationNetwork => "",
1797 studyHistory => "",
1798 studyComments => "",
1799 attributes => "",
1800 seasons => "",
1801 observationVariables => "",
1802 germplasm => \@germplasm_data,
1806 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1807 my %response = (metadata=>\%metadata, result=>\%result);
1808 $c->stash->{rest} = \%response;
1812 sub studies_layout : Chained('studies_single') PathPart('layout') Args(0) : ActionClass('REST') { }
1814 sub studies_layout_POST {
1815 my $self = shift;
1816 my $c = shift;
1817 my $auth = _authenticate_user($c);
1818 my $status = $c->stash->{status};
1819 my @status = @$status;
1821 $c->stash->{rest} = {status => \@status};
1824 sub studies_layout_GET {
1825 my $self = shift;
1826 my $c = shift;
1827 #my $auth = _authenticate_user($c);
1828 my $status = $c->stash->{status};
1829 my @status = @$status;
1830 my %result;
1831 my $total_count = 0;
1833 my $tl = CXGN::Trial::TrialLayout->new( { schema => $self->bcs_schema, trial_id => $c->stash->{study_id} });
1834 my $design = $tl->get_design();
1836 my $plot_data = [];
1837 my $formatted_plot = {};
1838 my %optional_info;
1839 my $check_id;
1840 my $type;
1842 foreach my $plot_number (keys %$design) {
1843 $check_id = $design->{$plot_number}->{is_a_control} ? 1 : 0;
1844 if ($check_id == 1) {
1845 $type = 'Check';
1846 } else {
1847 $type = 'Test';
1849 %optional_info = (germplasmName => $design->{$plot_number}->{accession_name}, blockNumber => $design->{$plot_number}->{block_number} ? $design->{$plot_number}->{block_number} : undef, rowNumber => $design->{$plot_number}->{row_number} ? $design->{$plot_number}->{row_number} : undef, columnNumber => $design->{$plot_number}->{col_number} ? $design->{$plot_number}->{col_number} : undef, type => $type);
1850 $formatted_plot = {
1851 studyDbId => $c->stash->{study_id},
1852 plotDbId => $design->{$plot_number}->{plot_id},
1853 plotName => $design->{$plot_number}->{plot_name},
1854 replicate => $design->{$plot_number}->{replicate} ? 1 : 0,
1855 germplasmDbId => $design->{$plot_number}->{accession_id},
1856 optionalInfo => \%optional_info
1858 push @$plot_data, $formatted_plot;
1859 $total_count += 1;
1861 %result = (data=>$plot_data);
1862 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1863 my %response = (metadata=>\%metadata, result=>\%result);
1864 $c->stash->{rest} = \%response;
1868 =head2 brapi/v1/studies/<studyDbId>/observationVariable/<observationVariableDbId>
1870 Usage: To retrieve phenotypic values on a the plot level for an entire trial
1871 Desc:
1872 Return JSON example:
1874 "metadata" : "status": [],
1875 "pagination": {
1876 "pageSize": 1,
1877 "currentPage": 1,
1878 "totalCount": 1,
1879 "totalPages": 1
1881 "result" : {
1882 "data" : [
1884 "studyDbId": 1,
1885 "plotDbId": 11,
1886 "observationVariableDbId" : 393939,
1887 "observationVariableName" : "Yield",
1888 "plotName": "ZIPA_68_Ibadan_2014",
1889 "timestamp" : "2015-11-05 15:12",
1890 "uploadedBy" : {dbUserId},
1891 "operator" : "Jane Doe",
1892 "germplasmName": 143,
1893 "value" : 5,
1898 Args:
1899 Side Effects:
1901 =cut
1903 sub studies_plot_phenotypes : Chained('studies_single') PathPart('observationVariable') Args(1) : ActionClass('REST') { }
1905 sub studies_plot_phenotypes_POST {
1906 my $self = shift;
1907 my $c = shift;
1908 my $trait_id = shift;
1909 my $auth = _authenticate_user($c);
1910 my $status = $c->stash->{status};
1911 my @status = @$status;
1913 $c->stash->{rest} = {status => \@status};
1916 sub studies_plot_phenotypes_GET {
1917 my $self = shift;
1918 my $c = shift;
1919 my $trait_id = shift;
1920 #my $auth = _authenticate_user($c);
1921 my $status = $c->stash->{status};
1922 my @status = @$status;
1923 my %result;
1925 my $t = $c->stash->{study};
1926 my $phenotype_data = $t->get_stock_phenotypes_for_trait($trait_id, 'plot');
1928 my $trait =$self->bcs_schema->resultset('Cv::Cvterm')->find({ cvterm_id => $trait_id });
1930 #print STDERR Dumper $phenotype_data;
1932 my @data;
1933 my $total_count = scalar(@$phenotype_data);
1934 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
1935 my $end = $c->stash->{page_size}*$c->stash->{current_page}-1;
1936 for( my $i = $start; $i <= $end; $i++ ) {
1937 if (@$phenotype_data[$i]) {
1938 my $pheno_uniquename = @$phenotype_data[$i]->[2];
1939 my ($part1 , $part2) = split( /date: /, $pheno_uniquename);
1940 my ($timestamp , $operator) = split( /\ \ operator = /, $part2);
1942 my $plot_id = @$phenotype_data[$i]->[0];
1943 my $stock_plot_relationship_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'plot_of', 'stock_relationship')->cvterm_id();
1944 my $germplasm =$self->bcs_schema->resultset('Stock::StockRelationship')->find({ 'me.subject_id' => $plot_id, 'me.type_id' =>$stock_plot_relationship_type_id }, {join => 'object', '+select'=> ['object.stock_id', 'object.uniquename'], '+as'=> ['germplasm_id', 'germplasm_name'] } );
1946 my %data_hash = (studyDbId => $c->stash->{study_id}, plotDbId => $plot_id, observationVariableDbId => $trait_id, observationVariableName => $trait->name(), plotName => @$phenotype_data[$i]->[1], timestamp => $timestamp, uploadedBy => @$phenotype_data[$i]->[3], operator => $operator, germplasmDbId => $germplasm->get_column('germplasm_id'), germplasmName => $germplasm->get_column('germplasm_name'), value => @$phenotype_data[$i]->[4] );
1947 push @data, \%data_hash;
1951 %result = (data=>\@data);
1952 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
1953 my %response = (metadata=>\%metadata, result=>\%result);
1954 $c->stash->{rest} = \%response;
1958 =head2 brapi/v1/studies/<studyDbId>/table
1960 Usage: To retrieve phenotypic values for a study, in a manner representative of a table, with headers and data separated
1961 Desc:
1962 Return JSON example:
1964 "metadata": {
1965 "status": [],
1966 "pagination": {
1967 "pageSize": 1,
1968 "currentPage": 1,
1969 "totalCount": 1,
1970 "totalPages": 1
1973 "result" : {
1974 "studyDbId": 1,
1975 "observationVariableDbId": [ '', '', '', '', '', '', '', '', 44444, 55555, 66666...],
1976 "observationVariableName": [ "plotDbId", "plotName", "block", "rep", "germplasmID", "germplasmName", "operator", "timestamp", "Yield", "Color", "Dry Matter"...],
1978 "data" :
1980 [1, "plot1", 1, 1, "CIP1", 41, "user1", "2015-11-05 15:12", 10, "yellow", 9, ...],
1981 [2, "plot2", 1, 1, "CIP2", 42, "user1", "2015-11-05 20:12", 3, "red", 4, ...]
1985 Args:
1986 Side Effects:
1988 =cut
1990 sub studies_table : Chained('studies_single') PathPart('table') Args(0) : ActionClass('REST') { }
1992 sub studies_table_POST {
1993 my $self = shift;
1994 my $c = shift;
1995 my $trait_id = shift;
1996 my $auth = _authenticate_user($c);
1997 my $status = $c->stash->{status};
1998 my @status = @$status;
2000 $c->stash->{rest} = {status => \@status};
2003 sub studies_table_GET {
2004 my $self = shift;
2005 my $c = shift;
2006 #my $auth = _authenticate_user($c);
2007 my $status = $c->stash->{status};
2008 my @status = @$status;
2009 my %result;
2011 my $timestamp = $c->req->param("timestamp") || 0;
2012 my $bs = CXGN::BreederSearch->new( { dbh => $self->bcs_schema->storage->dbh() });
2013 my $trial_id = $c->stash->{study_id};
2014 my $trial_sql = "\'$trial_id\'";
2015 my @data = $bs->get_extended_phenotype_info_matrix(undef,$trial_sql, undef, $timestamp);
2017 #print STDERR Dumper \@data;
2019 my $total_count = scalar(@data)-1;
2020 my @header_names = split /\t/, $data[0];
2021 #print STDERR Dumper \@header_names;
2022 my @trait_names = @header_names[11 .. $#header_names];
2023 #print STDERR Dumper \@trait_names;
2024 my @header_ids;
2025 foreach my $t (@trait_names) {
2026 push @header_ids, SGN::Model::Cvterm->get_cvterm_row_from_trait_name($self->bcs_schema, $t)->cvterm_id();
2029 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1)+1;
2030 my $end = $c->stash->{page_size}*$c->stash->{current_page}+1;
2031 my @data_window;
2032 for (my $line = $start; $line < $end; $line++) {
2033 if ($data[$line]) {
2034 my @columns = split /\t/, $data[$line], -1;
2036 push @data_window, \@columns;
2040 #print STDERR Dumper \@data_window;
2042 %result = (studyDbId => $c->stash->{study_id}, observationVariableDbId => \@header_ids, observationVariableName => \@header_names, data=>\@data_window);
2043 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2044 my %response = (metadata=>\%metadata, result=>\%result);
2045 $c->stash->{rest} = \%response;
2049 =head2 brapi/v1/phenotypes?observationUnitLevel=plot&studyDbId=876&studyPUI=&studyLocation=&studySet=&studyProject=&treatmentFactor=lowInput&germplasmGenus=&germplasmSubTaxa=&germplasmDbId&germplasmPUI=http://data.inra.fr/accession/234Col342&germplasmSpecies=Triticum&panel=diversitypanel1&collection=none&observationVariables=CO_321:000034,CO_321:000025&location=bergheim&season=2005,2006&pageSize={pageSize}&page={page}
2051 Usage: To retrieve a phenotype dataset
2052 Desc:d
2053 Return JSON example:
2055 "metadata": {
2056 "pagination": {
2057 "pageSize": 10,
2058 "currentPage": 1,
2059 "totalCount": 10,
2060 "totalPages": 1
2062 "status": []
2065 "result" : {
2066 "observationUnitDbId": 20,
2067 "observationUnitPUI": "http://phenome-fppn.fr/maugio/bloc/12/2345",
2068 "studyId": "RIGW1",
2069 "studyDbId": 25,
2070 "studyLocation": "Bergheim",
2071 "studyPUI": "http://phenome-fppn.fr/phenoarch/2014/1",
2072 "studyProject": "Inovine",
2073 "studySet": ["National Network", "Frost suceptibility network"],
2074 "studyPlatform": "Phenome",
2075 "observationUnitLevelTypes" : [ "plant","plot", "bloc"],
2076 "observationUnitLevelLabels": [ "1","26123", "1"],
2077 "germplasmPUI": "http://inra.fr/vassal/41207Col0001E",
2078 "germplasmDbId": 3425,
2079 "germplasmName": "charger",
2080 "treatments":
2083 "factor" : "water regimen" ,
2084 "modality":"water deficit"
2087 "attributes":
2089 {"att1" :"value"},
2090 {"numPot" :"23"}
2092 "X" : "",
2093 "Y" : "",
2094 "XLabel" : "",
2095 "YLabel" : "",
2096 "data": [
2098 "instanceNumber" : 1,
2099 "observationVariableId": "CO_321:0000045",
2100 //"observationVariableDbId": 35,
2101 "season": "2005",
2102 "observationValue" : "red",
2103 "observationTimeStamp": null,
2104 "quality": "reliability of the observation",
2105 "collectionFacilityLabel": "phenodyne",
2106 "collector" : "John Doe and team"
2109 "instanceNumber" : 1,
2110 "observationVariableId": "http://www.cropontology.org/rdf/CO_321:0000025",
2111 //"observationVariableDbId": 35,
2112 "season": null,
2113 "observationValue" : 32,
2114 "observationTimeStamp": "2006-07-03::10:00",
2115 "quality": "8",
2116 "collectionFacilityLabel": null,
2117 "collector" : "userURIOrName"
2123 Args:
2124 Side Effects:
2126 =cut
2128 sub phenotypes_dataset : Chained('brapi') PathPart('phenotypes') Args(0) : ActionClass('REST') { }
2130 sub phenotypes_dataset_POST {
2131 my $self = shift;
2132 my $c = shift;
2133 my $auth = _authenticate_user($c);
2134 my $status = $c->stash->{status};
2135 my @status = @$status;
2137 $c->stash->{rest} = {status => \@status};
2140 sub phenotypes_dataset_GET {
2141 my $self = shift;
2142 my $c = shift;
2143 #my $auth = _authenticate_user($c);
2144 my $status = $c->stash->{status};
2145 my $params = $c->req->params();
2146 my @status = @$status;
2148 my $study_id = $params->{studyDbId};
2149 my $t = CXGN::Trial->new( { trial_id => $study_id, bcs_schema => $self->bcs_schema } );
2150 my $traits_assayed = $t->get_traits_assayed();
2151 print STDERR Dumper $traits_assayed;
2153 my $count_limit = $c->stash->{page_size};
2154 foreach (@$traits_assayed) {
2155 if ($_->[2] < $count_limit) {
2159 $count_limit = $count_limit - $_->[2];
2163 my @data;
2165 my $total_count = '0';
2166 my %result = (
2167 observationUnitDbId =>
2168 data => \@data);
2169 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2170 my %response = (metadata=>\%metadata, result=>\%result);
2171 $c->stash->{rest} = \%response;
2176 sub traits_list : Chained('brapi') PathPart('traits') Args(0) : ActionClass('REST') { }
2178 sub traits_list_POST {
2179 my $self = shift;
2180 my $c = shift;
2181 my $auth = _authenticate_user($c);
2182 my $status = $c->stash->{status};
2183 my @status = @$status;
2185 $c->stash->{rest} = {status => \@status};
2188 sub traits_list_GET {
2189 my $self = shift;
2190 my $c = shift;
2191 #my $auth = _authenticate_user($c);
2192 my $status = $c->stash->{status};
2193 my @status = @$status;
2195 #my $db_rs = $self->bcs_schema()->resultset("General::Db")->search( { name => $c->config->{trait_ontology_db_name} } );
2196 #if ($db_rs->count ==0) { return undef; }
2197 #my $db_id = $db_rs->first()->db_id();
2199 #my $q = "SELECT cvterm.cvterm_id, cvterm.name, cvterm.definition, cvtermprop.value, dbxref.accession FROM cvterm LEFT JOIN cvtermprop using(cvterm_id) JOIN dbxref USING(dbxref_id) WHERE dbxref.db_id=?";
2200 #my $h = $self->bcs_schema()->storage->dbh()->prepare($q);
2201 #$h->execute($db_id);
2203 my $q = "SELECT cvterm_id, name FROM materialized_traits;";
2204 my $p = $self->bcs_schema()->storage->dbh()->prepare($q);
2205 $p->execute();
2207 my @data;
2208 while (my ($cvterm_id, $name) = $p->fetchrow_array()) {
2209 my $q2 = "SELECT cvterm.definition, cvtermprop.value, dbxref.accession FROM cvterm LEFT JOIN cvtermprop using(cvterm_id) JOIN dbxref USING(dbxref_id) WHERE cvterm.cvterm_id=?";
2210 my $h = $self->bcs_schema()->storage->dbh()->prepare($q2);
2211 $h->execute($cvterm_id);
2213 while (my ($description, $scale, $accession) = $h->fetchrow_array()) {
2214 my @observation_vars = ();
2215 push (@observation_vars, ($name, $accession));
2216 push @data, { traitDbId => $cvterm_id, traitId => $name, name => $name, description => $description, observationVariables => \@observation_vars, defaultValue => '', scale =>$scale };
2220 my $total_count = $p->rows;
2221 my %result = (data => \@data);
2222 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2223 my %response = (metadata=>\%metadata, result=>\%result);
2224 $c->stash->{rest} = \%response;
2228 sub traits_single : Chained('brapi') PathPart('traits') CaptureArgs(1) {
2229 my $self = shift;
2230 my $c = shift;
2231 #my $auth = _authenticate_user($c);
2232 my $cvterm_id = shift;
2233 my $status = $c->stash->{status};
2234 my @status = @$status;
2235 my %result;
2237 my $q = "SELECT cvterm_id, name FROM materialized_traits where cvterm_id=?;";
2238 my $p = $self->bcs_schema()->storage->dbh()->prepare($q);
2239 $p->execute($cvterm_id);
2241 while (my ($cvterm_id, $name) = $p->fetchrow_array()) {
2242 my $q2 = "SELECT cvterm.definition, cvtermprop.value, dbxref.accession FROM cvterm LEFT JOIN cvtermprop using(cvterm_id) JOIN dbxref USING(dbxref_id) WHERE cvterm.cvterm_id=?";
2243 my $h = $self->bcs_schema()->storage->dbh()->prepare($q2);
2244 $h->execute($cvterm_id);
2246 while (my ($description, $scale, $accession) = $h->fetchrow_array()) {
2247 my @observation_vars = ();
2248 push (@observation_vars, ($name, $accession));
2249 %result = ( traitDbId => $cvterm_id, traitId => $name, name => $name, description => $description, observationVariables => \@observation_vars, defaultValue => '', scale =>$scale );
2253 my $total_count = $p->rows;
2254 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2255 my %response = (metadata=>\%metadata, result=>\%result);
2256 $c->stash->{rest} = \%response;
2260 =head2 brapi/v1/maps?species=speciesId
2262 Usage: To retrieve a list of all maps available in the database.
2263 Desc:
2264 Return JSON example:
2266 "metadata" : {
2267 "pagination" : {
2268 "pageSize": 30,
2269 "currentPage": 2,
2270 "totalCount": 40,
2271 "totalPages": 2
2273 "status" : []
2275 "result": {
2276 "data" : [
2278 "mapId": 1,
2279 "name": "Some Map",
2280 "species": "Some species",
2281 "type": "Genetic",
2282 "unit": "cM",
2283 "publishedDate": "2008-04-16",
2284 "markerCount": 1000,
2285 "linkageGroupCount": 7,
2286 "comments": "This map contains ..."
2289 "mapId": 2,
2290 "name": "Some Other map",
2291 "species": "Some Species",
2292 "type": "Genetic",
2293 "unit": "cM",
2294 "publishedDate": "2009-01-12",
2295 "markerCount": 1501,
2296 "linkageGroupCount": 7,
2297 "comments": "this is blah blah"
2302 Args:
2303 Side Effects:
2305 =cut
2307 sub maps_list : Chained('brapi') PathPart('maps') Args(0) : ActionClass('REST') { }
2309 sub maps_list_POST {
2310 my $self = shift;
2311 my $c = shift;
2312 my $auth = _authenticate_user($c);
2313 my $status = $c->stash->{status};
2314 my @status = @$status;
2316 $c->stash->{rest} = {status => \@status};
2319 sub maps_list_GET {
2320 my $self = shift;
2321 my $c = shift;
2322 #my $auth = _authenticate_user($c);
2323 my $status = $c->stash->{status};
2324 my @status = @$status;
2326 my $snp_genotyping_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'snp genotyping', 'genotype_property')->cvterm_id();
2327 my $rs = $self->bcs_schema()->resultset("NaturalDiversity::NdProtocol")->search( { } );
2329 my @data;
2330 while (my $row = $rs->next()) {
2331 my %map_info;
2332 print STDERR "Retrieving map info for ".$row->name()." ID:".$row->nd_protocol_id()."\n";
2333 #$self->bcs_schema->storage->debug(1);
2334 my $lg_rs = $self->bcs_schema()->resultset("NaturalDiversity::NdProtocol")->search( { 'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'me.nd_protocol_id' => $row->nd_protocol_id() } )->search_related('nd_experiment_protocols')->search_related('nd_experiment')->search_related('nd_experiment_genotypes')->search_related('genotype')->search_related('genotypeprops', {}, {select=>['genotype.description', 'genotypeprops.value'], as=>['description', 'value'], rows=>1, order_by=>{ -asc => 'genotypeprops.genotypeprop_id' }} );
2336 my $lg_row = $lg_rs->first();
2338 if (!$lg_row) {
2339 die "This was never supposed to happen :-(";
2342 my $scores = JSON::Any->decode($lg_row->get_column('value'));
2343 my %chrs;
2345 my $marker_count =0;
2346 foreach my $m (sort genosort (keys %$scores)) {
2347 my ($chr, $pos) = split "_", $m;
2348 #print STDERR "CHR: $chr. POS: $pos\n";
2349 $chrs{$chr} = $pos;
2350 $marker_count++;
2352 my $lg_count = scalar(keys(%chrs));
2354 %map_info = (
2355 mapId => $row->nd_protocol_id(),
2356 name => $row->name(),
2357 species => $lg_row->get_column('description'),
2358 type => "physical",
2359 unit => "bp",
2360 markerCount => $marker_count,
2361 publishedDate => undef,
2362 comments => "",
2363 linkageGroupCount => $lg_count,
2366 push @data, \%map_info;
2369 my $total_count = scalar(@data);
2370 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
2371 my $end = $c->stash->{page_size}*$c->stash->{current_page};
2372 my @data_window = splice @data, $start, $end;
2374 my %result = (data => \@data_window);
2375 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2376 my %response = (metadata=>\%metadata, result=>\%result);
2377 $c->stash->{rest} = \%response;
2382 =head2 brapi/v1/maps/<map_id>
2384 Usage: To retrieve details for a specific map_id
2385 Desc:
2386 Return JSON example:
2388 "metadata" : {
2389 "pagination" : {
2390 "pageSize": 30,
2391 "currentPage": 2,
2392 "totalCount": 40,
2393 "totalPages": 2
2395 "status" : []
2397 "result": {
2398 "mapId": "id",
2399 "name": "Some map",
2400 "type": "Genetic",
2401 "unit": "cM",
2402 "linkageGroups": [
2404 "linkageGroupId": 1,
2405 "numberMarkers": 100000,
2406 "maxPosition": 10000000
2409 "linkageGroupId": 2,
2410 "numberMarkers": 1247,
2411 "maxPostion": 12347889
2416 Args:
2417 Side Effects:
2419 =cut
2421 sub maps_single : Chained('brapi') PathPart('maps') CaptureArgs(1) {
2422 my $self = shift;
2423 my $c = shift;
2424 my $map_id = shift;
2426 $c->stash->{map_id} = $map_id;
2430 sub maps_details : Chained('maps_single') PathPart('') Args(0) : ActionClass('REST') { }
2432 sub maps_details_POST {
2433 my $self = shift;
2434 my $c = shift;
2435 my $auth = _authenticate_user($c);
2436 my $status = $c->stash->{status};
2437 my @status = @$status;
2439 $c->stash->{rest} = {status => \@status};
2442 sub maps_details_GET {
2443 my $self = shift;
2444 my $c = shift;
2445 #my $auth = _authenticate_user($c);
2446 my $status = $c->stash->{status};
2447 my @status = @$status;
2448 my $params = $c->req->params();
2449 my $total_count = 0;
2451 my $snp_genotyping_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'snp genotyping', 'genotype_property')->cvterm_id();
2453 # maps are just marker lists associated with specific protocols
2454 my $rs = $self->bcs_schema()->resultset("NaturalDiversity::NdProtocol")->find( { nd_protocol_id => $c->stash->{map_id} } );
2455 my %map_info;
2456 my @data;
2458 print STDERR "Retrieving map info for ".$rs->name()."\n";
2459 #$self->bcs_schema->storage->debug(1);
2460 my $lg_rs = $self->bcs_schema()->resultset("NaturalDiversity::NdExperimentProtocol")->search( { 'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'me.nd_protocol_id' => $rs->nd_protocol_id() })->search_related('nd_experiment')->search_related('nd_experiment_genotypes')->search_related('genotype')->search_related('genotypeprops', {}, {rows=>1, order_by=>{ -asc => 'genotypeprops.genotypeprop_id' }} );
2462 if (!$lg_rs) {
2463 die "This was never supposed to happen :-(";
2466 my %chrs;
2467 my %markers;
2468 my @ordered_refmarkers;
2469 while (my $profile = $lg_rs->next()) {
2470 my $profile_json = $profile->value();
2471 my $refmarkers = JSON::Any->decode($profile_json);
2472 #print STDERR Dumper($refmarkers);
2473 push @ordered_refmarkers, sort genosort keys(%$refmarkers);
2477 foreach my $m (@ordered_refmarkers) {
2479 my ($chr, $pos) = split "_", $m;
2480 #print STDERR "CHR: $chr. POS: $pos\n";
2482 $markers{$chr}->{$m} = 1;
2483 if ($pos) {
2484 if ($chrs{$chr}) {
2485 if ($pos > $chrs{$chr}) {
2486 $chrs{$chr} = $pos;
2488 } else {
2489 $chrs{$chr} = $pos;
2495 foreach my $ci (sort (keys %chrs)) {
2496 my $num_markers = scalar keys %{ $markers{$ci} };
2497 my %linkage_groups_data = (linkageGroupId => $ci, numberMarkers => $num_markers, maxPosition => $chrs{$ci} );
2498 push @data, \%linkage_groups_data;
2501 $total_count = scalar(@data);
2502 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
2503 my $end = $c->stash->{page_size}*$c->stash->{current_page};
2504 my @data_window = splice @data, $start, $end;
2506 %map_info = (
2507 mapId => $rs->nd_protocol_id(),
2508 name => $rs->name(),
2509 type => "physical",
2510 unit => "bp",
2511 linkageGroups => \@data_window,
2514 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2515 my %response = (metadata=>\%metadata, result=>\%map_info);
2516 $c->stash->{rest} = \%response;
2520 =head2 brapi/v1/maps/<map_id>/position?linkageGroupIdList=1,2,3
2522 Usage: To retrieve marker position data for a species map_id. Can provide a list of linkage groups (e.g. chromosomes) to narrow result set.
2523 Desc:
2524 Return JSON example:
2526 "metadata" : {
2527 "pagination" : { "pageSize": 30, "currentPage": 2, "totalCount": 40, "totalPages":2 },
2528 "status: []
2530 "result": {
2531 "data" : [
2533 "markerId": 1,
2534 "markerName": "marker1",
2535 "location": "1000",
2536 "linkageGroup": "1A"
2537 }, {
2538 "markerId": 2,
2539 "markerName": "marker2",
2540 "location": "1001",
2541 "linkageGroup": "1A"
2546 Args:
2547 Side Effects:
2549 =cut
2551 sub maps_marker_detail : Chained('maps_single') PathPart('positions') Args(0) : ActionClass('REST') { }
2553 sub maps_marker_detail_POST {
2554 my $self = shift;
2555 my $c = shift;
2556 my $auth = _authenticate_user($c);
2557 my $status = $c->stash->{status};
2558 my @status = @$status;
2560 $c->stash->{rest} = {status => \@status};
2563 sub maps_marker_detail_GET {
2564 my $self = shift;
2565 my $c = shift;
2566 #my $auth = _authenticate_user($c);
2567 my $status = $c->stash->{status};
2568 my @status = @$status;
2569 my $params = $c->req->params();
2571 my %linkage_groups;
2572 if ($params->{linkageGroupIdList}) {
2573 my $linkage_groups_list = $params->{linkageGroupIdList};
2574 my @linkage_groups_array = split /,/, $linkage_groups_list;
2575 %linkage_groups = map { $_ => 1 } @linkage_groups_array;
2578 my $snp_genotyping_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'snp genotyping', 'genotype_property')->cvterm_id();
2579 my $rs = $self->bcs_schema()->resultset("NaturalDiversity::NdProtocol")->find( { nd_protocol_id => $c->stash->{map_id} } );
2581 my @markers;
2582 print STDERR "Retrieving map info for ".$rs->name()."\n";
2583 #$self->bcs_schema->storage->debug(1);
2584 my $lg_rs = $self->bcs_schema()->resultset("NaturalDiversity::NdProtocol")->search( { 'genotypeprops.type_id' => $snp_genotyping_cvterm_id, 'me.nd_protocol_id' => $rs->nd_protocol_id()})->search_related('nd_experiment_protocols')->search_related('nd_experiment')->search_related('nd_experiment_genotypes')->search_related('genotype')->search_related('genotypeprops', {}, {rows=>1, order_by=>{ -asc => 'genotypeprops.genotypeprop_id' }} );
2586 if (!$lg_rs) {
2587 die "This was never supposed to happen :-(";
2590 my @ordered_refmarkers;
2591 while (my $profile = $lg_rs->next()) {
2592 my $profile_json = $profile->value();
2593 my $refmarkers = JSON::Any->decode($profile_json);
2594 #print STDERR Dumper($refmarkers);
2595 push @ordered_refmarkers, sort genosort keys(%$refmarkers);
2598 my %chrs;
2600 foreach my $m (@ordered_refmarkers) {
2601 my ($chr, $pos) = split "_", $m;
2602 #print STDERR "CHR: $chr. POS: $pos\n";
2603 $chrs{$chr} = $pos;
2604 # "markerId": 1,
2605 # "markerName": "marker1",
2606 # "location": "1000",
2607 # "linkageGroup": "1A"
2609 if (%linkage_groups) {
2610 if (exists $linkage_groups{$chr} ) {
2611 if ($params->{min} && $params->{max}) {
2612 if ($pos >= $params->{min} && $pos <= $params->{max}) {
2613 push @markers, { markerId => $m, markerName => $m, location => $pos, linkageGroup => $chr };
2615 } elsif ($params->{min}) {
2616 if ($pos >= $params->{min}) {
2617 push @markers, { markerId => $m, markerName => $m, location => $pos, linkageGroup => $chr };
2619 } elsif ($params->{max}) {
2620 if ($pos <= $params->{max}) {
2621 push @markers, { markerId => $m, markerName => $m, location => $pos, linkageGroup => $chr };
2623 } else {
2624 push @markers, { markerId => $m, markerName => $m, location => $pos, linkageGroup => $chr };
2627 } else {
2628 push @markers, { markerId => $m, markerName => $m, location => $pos, linkageGroup => $chr };
2633 my $total_count = scalar(@markers);
2634 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
2635 my $end = $c->stash->{page_size}*$c->stash->{current_page};
2636 my @data_window = splice @markers, $start, $end;
2638 my %result = (data => \@data_window);
2639 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2640 my %response = (metadata=>\%metadata, result=>\%result);
2641 $c->stash->{rest} = \%response;
2645 sub locations_list : Chained('brapi') PathPart('locations') Args(0) : ActionClass('REST') { }
2647 sub locations_list_POST {
2648 my $self = shift;
2649 my $c = shift;
2650 my $auth = _authenticate_user($c);
2651 my $status = $c->stash->{status};
2652 my @status = @$status;
2654 $c->stash->{rest} = {status => \@status};
2657 sub locations_list_GET {
2658 my $self = shift;
2659 my $c = shift;
2660 #my $auth = _authenticate_user($c);
2661 my $status = $c->stash->{status};
2662 my @status = @$status;
2663 my @data;
2664 my @attributes;
2666 my $locations = CXGN::Trial::get_all_locations($self->bcs_schema);
2668 my $total_count = scalar(@$locations);
2669 my $start = $c->stash->{page_size}*($c->stash->{current_page}-1);
2670 my $end = $c->stash->{page_size}*$c->stash->{current_page}-1;
2671 for( my $i = $start; $i <= $end; $i++ ) {
2672 if (@$locations[$i]) {
2673 push @data, {locationDbId => @$locations[$i]->[0], name=> @$locations[$i]->[1], countryCode=> @$locations[$i]->[6], countryName=> @$locations[$i]->[5], latitude=>@$locations[$i]->[2], longitude=>@$locations[$i]->[3], altitude=>@$locations[$i]->[4], attributes=> @$locations[$i]->[7]};
2677 my %result = (data=>\@data);
2678 my %metadata = (pagination=>pagination_response($total_count, $c->stash->{page_size}, $c->stash->{current_page}), status=>\@status);
2679 my %response = (metadata=>\%metadata, result=>\%result);
2680 $c->stash->{rest} = \%response;
2685 sub authenticate : Chained('brapi') PathPart('authenticate/oauth') Args(0) {
2686 my $self = shift;
2687 my $c = shift;
2689 $c->res->redirect("https://accounts.google.com/o/oauth2/auth?scope=profile&response_type=code&client_id=1068256137120-62dvk8sncnbglglrmiroms0f5d7lg111.apps.googleusercontent.com&redirect_uri=https://cassavabase.org/oauth2callback");
2691 $c->stash->{rest} = { success => 1 };