Merge pull request #5230 from solgenomics/topic/open_pollinated
[sgn.git] / lib / SGN / Model / solGS / solGS.pm
blobd6e7ad31ecc72c02c2506e0c9c673a38165decce
2 =head1 NAME
4 solGS::Model::solGS - Catalyst Model for solGS
6 =head1 DESCRIPTION
8 solGS Catalyst Model.
10 =head1 AUTHOR
12 Isaak Y Tecle, iyt2@cornell.edu
14 =head1 LICENSE
16 This library is free software. You can redistribute it and/or modifyi
17 t under the same terms as Perl itself.
19 =cut
21 package SGN::Model::solGS::solGS;
23 use Moose;
25 use namespace::autoclean;
26 use Array::Utils qw(:all);
27 use Bio::Chado::Schema;
28 use CXGN::People::Schema;
30 use Bio::Chado::NaturalDiversity::Reports;
31 use File::Path qw / mkpath /;
32 use File::Spec::Functions;
33 use List::MoreUtils qw / uniq /;
34 use JSON::Any;
35 use Scalar::Util qw(looks_like_number);
36 use File::Spec::Functions qw / catfile catdir/;
37 use File::Slurp qw /write_file read_file :edit prepend_file/;
38 use Math::Round::Var;
39 use CXGN::Genotype::Search;
40 use CXGN::Trial;
41 use CXGN::Dataset;
42 use CXGN::Phenotypes::PhenotypeMatrix;
43 use Data::Dumper;
45 # extends 'Catalyst::Model';
47 has 'schema' => (
48 isa => 'Ref',
49 is => 'rw',
50 required => 1
53 has 'people_schema' => (
54 isa => 'Ref',
55 is => 'rw',
56 required => 1
59 sub search_trait {
60 my ( $self, $trait ) = @_;
62 my $q = "SELECT distinct(cvterm.name) FROM genotyping_protocolsXtrials
63 LEFT JOIN traitsXtrials ON genotyping_protocolsXtrials.trial_id = traitsXtrials.trial_id
64 LEFT JOIN cvterm ON cvterm.cvterm_id = traitsXtrials.trait_id
65 LEFT JOIN locationsXtrials ON traitsXtrials.trial_id = locationsXtrials.trial_id
66 LEFT JOIN locations ON locations.location_id = locationsXtrials.location_id
67 WHERE location_name NOT LIKE '[Computation]'
68 AND cvterm.name ILIKE ?
69 ORDER BY cvterm.name";
71 my $sth = $self->schema->storage->dbh->prepare($q);
73 $sth->execute("%$trait%");
75 my @traits;
77 while ( my $tr = $sth->fetchrow_array() ) {
78 push @traits, $tr;
81 return \@traits;
85 # sub search_trait {
86 # my ($self, $trait) = @_;
88 # my $q = "SELECT name FROM all_gs_traits
89 # WHERE name ilike ?
90 # ORDER BY name";
92 # my $sth = $self->schema->storage->dbh->prepare($q);
94 # $sth->execute("%$trait%");
96 # my @traits;
98 # while ( my $trait = $sth->fetchrow_array())
99 # {
100 # push @traits, $trait;
103 # return \@traits;
107 sub trait_details {
108 my ( $self, $trait_arrayref ) = @_;
110 my $rs = $self->schema->resultset("Cv::Cvterm")->search(
111 { 'me.name' => { -in => $trait_arrayref } },
113 'select' => [qw / me.cvterm_id me.name me.definition /],
114 'as' => [qw / cvterm_id name definition /]
118 return $rs;
122 sub all_gs_traits {
123 my $self = shift;
125 my $q = "SELECT distinct(cvterm.name) FROM genotyping_protocolsXtrials
126 LEFT JOIN traitsXtrials ON genotyping_protocolsXtrials.trial_id = traitsXtrials.trial_id
127 LEFT JOIN cvterm ON cvterm.cvterm_id = traitsXtrials.trait_id
128 LEFT JOIN locationsXtrials ON traitsXtrials.trial_id = locationsXtrials.trial_id
129 LEFT JOIN locations ON locations.location_id = locationsXtrials.location_id
130 WHERE location_name NOT LIKE '[Computation]'
131 ORDER BY cvterm.name";
133 my $sth = $self->schema->storage->dbh->prepare($q);
135 $sth->execute();
137 my @traits;
139 while ( my ( $cvterm, $cvterm_id ) = $sth->fetchrow_array() ) {
140 push @traits, $cvterm;
143 return \@traits;
146 sub materialized_view_all_gs_traits {
147 my $self = shift;
149 my $q = "CREATE MATERIALIZED VIEW public.all_gs_traits
150 AS SELECT observable.cvterm_id, observable.name
151 FROM phenotype me
152 JOIN cvterm observable ON observable.cvterm_id = me.observable_id
153 GROUP BY observable.cvterm_id, observable.name";
155 my $sth = $self->schema->storage->dbh->prepare($q);
157 $sth->execute();
161 sub insert_matview_public {
162 my ( $self, $name ) = @_;
164 my $q =
165 "INSERT INTO public.matviews (mv_name, last_refresh) VALUES (?, now())";
167 my $sth = $self->schema->storage->dbh->prepare($q);
169 $sth->execute($name);
173 sub update_matview_public {
174 my ( $self, $name ) = @_;
176 my $q =
177 "Update public.matviews SET last_refresh = now() WHERE mv_name ilike ? ";
179 my $sth = $self->schema->storage->dbh->prepare($q);
181 $sth->execute($name);
185 sub check_matview_exists {
186 my ( $self, $name ) = @_;
188 my $q = "SELECT mv_name FROM public.matviews WHERE mv_name ilike ?";
190 my $sth = $self->schema->storage->dbh->prepare($q);
192 $sth->execute($name);
194 my $exists = $sth->fetchrow_array();
196 return $exists;
200 sub refresh_materialized_view_all_gs_traits {
201 my $self = shift;
203 my $q = "REFRESH MATERIALIZED VIEW public.all_gs_traits";
205 my $sth = $self->schema->storage->dbh->prepare($q);
207 $sth->execute();
211 sub search_trait_trials {
212 my ( $self, $trait_id, $protocol_id ) = @_;
214 #my $q = "SELECT distinct(trial_id) FROM traitsXtrials ORDER BY trial_id";
215 my $protocol_detail = $self->protocol_detail($protocol_id);
216 my $protocol = $protocol_detail->{name};
218 my $q = "SELECT distinct(trial_id)
219 FROM materialized_phenoview
220 JOIN genotyping_protocolsXtrials USING (trial_id)
221 JOIN genotyping_protocols USING (genotyping_protocol_id)
222 WHERE genotyping_protocols.genotyping_protocol_name ILIKE ?
223 AND trait_id = ?";
225 my $sth = $self->schema->storage->dbh->prepare($q);
227 $sth->execute( $protocol, $trait_id );
229 my @trials;
231 while ( my $trial_id = $sth->fetchrow_array() ) {
232 push @trials, $trial_id;
235 return \@trials;
239 sub search_populations {
240 my ( $self, $trait_id, $page ) = @_;
242 my $rs =
243 $self->schema->resultset("Phenotype::Phenotype")
244 ->search(
245 { 'me.observable_id' => $trait_id, 'me.value' => { '!=', undef } } )
246 ->search_related('nd_experiment_phenotypes')
247 ->search_related('nd_experiment')->search_related('nd_experiment_stocks')
248 ->search_related('stock')->search_related('nd_experiment_stocks')
249 ->search_related('nd_experiment')
250 ->search_related('nd_experiment_projects')->search_related(
251 'project',
254 page => $page,
255 rows => 10,
256 order_by =>
257 'CASE WHEN project.name ~ \'^[0-9]+\' THEN 1 ELSE 0 END, project.name',
259 'select' =>
260 [qw / project.project_id project.name project.description /],
261 'as' => [qw / project_id name description /],
262 distinct => [qw / project.project_id /]
266 return $rs;
270 sub project_year {
271 my ( $self, $pr_id ) = @_;
273 return $self->schema->resultset("Cv::Cvterm")
274 ->search( { 'project_id' => $pr_id, 'me.name' => 'project year' } )
275 ->search_related(
276 'projectprops',
279 select => [qw /projectprops.value/]
284 sub experimental_design {
285 my ( $self, $pr_id ) = @_;
287 return $self->schema->resultset("Cv::Cvterm")
288 ->search( { 'project_id' => $pr_id, 'me.name' => 'design' } )
289 ->search_related(
290 'projectprops',
293 select => [qw /projectprops.value/]
299 sub project_location {
300 my ( $self, $pr_id ) = @_;
302 my $q = "SELECT location_name
303 FROM locationsXtrials
304 JOIN locations USING (location_id)
305 WHERE trial_id = ?";
307 my $sth = $self->schema->storage->dbh()->prepare($q);
309 $sth->execute($pr_id);
311 my $loc = $sth->fetchrow_array;
313 return $loc;
316 sub all_gs_projects {
317 my ( $self, $limit ) = @_;
319 my $protocol = $self->genotyping_protocol();
320 $limit = 'LIMIT ' . $limit if $limit;
322 my $order_by =
323 'CASE WHEN trials.trial_name ~ \'\\m[0-9]+\' THEN 1 ELSE 0 END, trials.trial_name DESC';
325 my $q = "SELECT trials.trial_name, trials.trial_id
326 FROM traits
327 JOIN traitsXtrials USING (trait_id)
328 JOIN trials USING (trial_id)
329 JOIN genotyping_protocolsXtrials USING (trial_id)
330 JOIN genotyping_protocols USING (genotyping_protocol_id)
331 WHERE genotyping_protocols.genotyping_protocol_name ILIKE ?
332 GROUP BY trials.trial_id, trials.trial_name
333 ORDER BY $order_by
334 $limit";
336 my $sth = $self->schema->storage->dbh()->prepare($q);
338 $sth->execute($protocol);
340 my @gs_trials;
342 while ( my ( $trial_name, $trial_id ) = $sth->fetchrow_array() ) {
343 push @gs_trials, $trial_id;
346 return \@gs_trials;
350 sub all_projects {
351 my ( $self, $page, $rows ) = @_;
353 $rows = 10 if !$rows;
354 $page = 1 if !$page;
356 if ( $rows eq 'all' ) { $rows = undef; $page = undef; }
358 my $projects_rs = $self->schema->resultset("Project::Project")->search(
361 distinct => 1,
362 page => $page,
363 rows => $rows,
364 order_by => 'CASE WHEN name ~ \'^[0-9]+\' THEN 1 ELSE 0 END, name'
369 return $projects_rs;
372 sub get_trial_accessions {
373 my ($self, $trial_id, $limit) = @_;
375 $limit = $limit ? " LIMIT $limit" : '';
376 my $q = "SELECT accession_id FROM accessionsXtrials WHERE trial_id = ? $limit";
378 my $sth = $self->schema->storage->dbh->prepare($q);
379 $sth->execute($trial_id);
381 my @accessions_ids;
382 while (my $accession_id = $sth->fetchrow_array()) {
383 push @accessions_ids, $accession_id;
386 return \@accessions_ids;
391 sub has_phenotype {
392 my ( $self, $pr_id ) = @_;
394 my $has_phenotype;
396 if ($pr_id) {
397 my $q = "SELECT distinct(trait_id)
398 FROM materialized_phenoview
399 WHERE trial_id = ?
400 AND trait_id IS NOT NULL";
402 my $sth = $self->schema->storage->dbh->prepare($q);
403 $sth->execute($pr_id);
405 while ( $has_phenotype = $sth->fetchrow_array() ) {
406 last if $has_phenotype;
410 return $has_phenotype;
414 sub has_genotype {
415 my ($self, $trial_id, $protocol_id) = @_;
417 my $has_genotype;
418 my $q = "SELECT genotyping_protocol_name, genotyping_protocol_id
419 FROM genotyping_protocolsXtrials
420 JOIN genotyping_protocols USING (genotyping_protocol_id)
421 WHERE trial_id = ?
422 AND genotyping_protocols.genotyping_protocol_id = ?";
424 my $sth = $self->schema->storage->dbh->prepare($q);
425 $sth->execute($trial_id, $protocol_id);
427 my ($protocol_name, $protocol_id_geno ) = $sth->fetchrow_array();
428 $has_genotype = 1 if $protocol_name;
430 if (!$has_genotype) {
431 my $accessions_ids = $self->get_trial_accessions($trial_id, 10);
432 my $geno_data = $self->first_stock_genotype_data($accessions_ids, $protocol_id);
434 $has_genotype = 1 if $$geno_data;
437 return $has_genotype;
441 sub project_details {
442 my ( $self, $pr_id ) = @_;
444 if ( ref $pr_id eq 'SCALAR' ) {
445 $pr_id = [$pr_id];
448 my $pr_rs = $self->schema->resultset("Project::Project")
449 ->search( { 'me.project_id' => { -in => $pr_id } } );
451 return $pr_rs;
455 sub project_details_by_name {
456 my ( $self, $pr_name ) = @_;
458 return $self->schema->resultset("Project::Project")
459 ->search( { 'me.name' => { 'iLIKE' => '%' . $pr_name . '%' } } );
462 sub project_details_by_exact_name {
463 my ( $self, $pr_name ) = @_;
465 return $self->schema->resultset("Project::Project")
466 ->search( { 'me.name' => { -in => $pr_name } } );
469 sub get_population_details {
470 my ( $self, $pop_id ) = @_;
472 return $self->schema->resultset("Stock::Stock")->search(
474 'stock_id' => $pop_id
479 sub trait_name {
480 my ( $self, $trait_id ) = @_;
482 my $trait_name;
483 if ($trait_id) {
484 $trait_name = $self->schema->resultset('Cv::Cvterm')
485 ->search( { cvterm_id => $trait_id } )->single->name;
488 return $trait_name;
492 sub get_trait_id {
493 my ( $self, $trait ) = @_;
495 if ($trait) {
496 my $trait_rs =
497 $self->schema->resultset('Cv::Cvterm')->search( { name => $trait } );
499 if ( $trait_rs->single ) {
500 return $trait_rs->single->id;
502 else {
503 return;
509 sub check_stock_type {
510 my ( $self, $stock_id ) = @_;
512 my $type_id = $self->schema->resultset("Stock::Stock")
513 ->search( { 'stock_id' => $stock_id } )->first()->type_id;
515 return $self->schema->resultset('Cv::Cvterm')
516 ->search( { cvterm_id => $type_id } )->first()->name;
519 sub set_project_genotypeprop {
520 my ( $self, $prop ) = @_;
522 my $cv_id = $self->schema->resultset("Cv::Cv")
523 ->find_or_create( { 'name' => 'project_property' } )->cv_id;
525 my $db_id = $self->schema->resultset("General::Db")
526 ->find_or_new( { 'name' => 'null' } )->db_id;
528 my $dbxref_id =
529 $self->schema->resultset("General::Dbxref")
530 ->find_or_create( { 'accession' => 'marker_count', 'db_id' => $db_id } )
531 ->dbxref_id;
533 my $cvterm_id =
534 $self->schema->resultset("Cv::Cvterm")
535 ->find_or_create(
536 { name => 'marker_count', cv_id => $cv_id, dbxref_id => $dbxref_id, } )
537 ->cvterm_id;
539 my $marker_rs =
540 $self->schema->resultset("Project::Projectprop")
541 ->search(
542 { project_id => $prop->{'project_id'}, type_id => $cvterm_id } );
544 my $marker;
546 while ( my $row = $marker_rs->next ) {
547 $marker = $row->value;
550 if ($marker) {
551 my $project_rs =
552 $self->schema->resultset("Project::Projectprop")
553 ->search(
554 { project_id => $prop->{'project_id'}, type_id => $cvterm_id } )
555 ->update( { value => $prop->{'marker_count'} } );
557 else {
558 my $project_rs =
559 $self->schema->resultset("Project::Projectprop")->create(
561 project_id => $prop->{'project_id'},
562 type_id => $cvterm_id,
563 value => $prop->{'marker_count'}
570 sub get_project_genotypeprop {
571 my ( $self, $pr_id ) = @_;
573 my $cvterm_rs =
574 $self->schema->resultset("Cv::Cvterm")
575 ->search( { 'project_id' => $pr_id, 'me.name' => 'marker_count' } )
576 ->search_related('projectprops');
578 my $marker_count;
579 if ( $cvterm_rs->next ) {
580 $marker_count = $cvterm_rs->first()->value;
583 my $genoprop = { 'marker_count' => $marker_count };
585 return $genoprop;
588 sub set_project_type {
589 my ( $self, $prop ) = @_;
591 my $cv_id = $self->schema->resultset("Cv::Cv")
592 ->find_or_create( { 'name' => 'project_property' } )->cv_id;
594 my $db_id = $self->schema->resultset("General::Db")
595 ->find_or_new( { 'name' => 'null' } )->db_id;
597 my $dbxref_id =
598 $self->schema->resultset("General::Dbxref")->find_or_create(
600 'accession' => 'genomic selection',
601 'db_id' => $db_id
603 )->dbxref_id;
605 my $cvterm_id = $self->schema->resultset("Cv::Cvterm")->find_or_create(
607 name => 'genomic selection',
608 cv_id => $cv_id,
609 dbxref_id => $dbxref_id,
611 )->cvterm_id;
613 my $project_rs =
614 $self->schema->resultset("Project::Projectprop")->find_or_create(
616 project_id => $prop->{'project_id'},
617 type_id => $cvterm_id,
618 value => $prop->{'project_type'},
623 sub get_project_type {
624 my ( $self, $pr_id ) = @_;
626 my $pr_rs =
627 $self->schema->resultset("Cv::Cvterm")
628 ->search( { 'project_id' => $pr_id, 'me.name' => 'genomic selection' } )
629 ->search_related(
630 'projectprops',
633 select => [qw /projectprops.value/]
637 my $pr_type;
638 if ( $pr_rs->next ) {
639 $pr_type = $pr_rs->first()->value;
642 return $pr_type;
645 sub set_population_type {
646 my ( $self, $prop ) = @_;
648 my $cv_id = $self->schema->resultset("Cv::Cv")
649 ->find_or_create( { 'name' => 'project_property' } )->cv_id;
651 my $db_id = $self->schema->resultset("General::Db")
652 ->find_or_new( { 'name' => 'null' } )->db_id;
654 my $dbxref_id =
655 $self->schema->resultset("General::Dbxref")->find_or_create(
657 'accession' => 'population type',
658 'db_id' => $db_id
660 )->dbxref_id;
662 my $cvterm_id = $self->schema->resultset("Cv::Cvterm")->find_or_create(
664 name => 'population type',
665 cv_id => $cv_id,
666 dbxref_id => $dbxref_id,
668 )->cvterm_id;
670 my $project_rs =
671 $self->schema->resultset("Project::Projectprop")->find_or_create(
673 project_id => $prop->{'project_id'},
674 type_id => $cvterm_id,
675 value => $prop->{'population type'},
680 sub get_population_type {
681 my ( $self, $pr_id ) = @_;
683 my $pr_rs =
684 $self->schema->resultset("Cv::Cvterm")
685 ->search( { 'project_id' => $pr_id, 'me.name' => 'population type' } )
686 ->search_related('projectprops');
688 my $pr_type;
689 if ( $pr_rs->next ) {
690 $pr_type = $pr_rs->first()->value;
693 return $pr_type;
696 sub get_stock_owners {
697 my ( $self, $stock_id ) = @_;
699 my @owners;
701 no warnings 'uninitialized';
703 unless ( $stock_id =~ /list/ ) {
704 my $q = "SELECT sp_person_id, first_name, last_name
705 FROM phenome.stock_owner
706 JOIN sgn_people.sp_person USING (sp_person_id)
707 WHERE stock_id = ? ";
709 my $sth = $self->schema->storage->dbh()->prepare($q);
710 $sth->execute($stock_id);
712 while ( my ( $id, $fname, $lname ) = $sth->fetchrow_array ) {
714 push @owners,
716 'id' => $id,
717 'first_name' => $fname,
718 'last_name' => $lname
724 return \@owners;
728 sub search_stock {
729 my ( $self, $stock_name ) = @_;
731 my $rs = $self->schema->resultset("Stock::Stock")
732 ->search( { 'me.uniquename' => $stock_name } );
734 return $rs;
738 sub search_plotprop {
739 my ( $self, $plot_id, $type ) = @_;
741 my $rs =
742 $self->schema->resultset("Cv::Cvterm")
743 ->search( { 'stock_id' => $plot_id, 'name' => $type } )
744 ->search_related('stockprops');
746 return $rs;
750 sub search_stock_using_plot_name {
751 my ( $self, $plot_name ) = @_;
753 my $rs = $self->schema->resultset("Stock::Stock")
754 ->search( { 'me.uniquename' => { -in => $plot_name } } );
756 return $rs;
760 sub first_stock_genotype_data {
761 my ($self, $accessions_ids, $protocol_id) = @_;
763 my $geno_data = do { \my $geno_data};
764 my $geno_search = $self->genotypes_list_genotype_data($accessions_ids, $protocol_id);
765 my $count = 1;
767 while (my $geno = $geno_search->get_next_genotype_info())
769 my $geno_hash = $geno->{selected_genotype_hash};
770 my $marker_headers = $self->get_dataset_markers($geno_hash);
771 $geno_data = $self->structure_genotype_data($geno, $marker_headers, $count);
772 $count++;
773 last if $$geno_data;
776 return $geno_data;
780 sub genotype_data {
781 my ( $self, $args ) = @_;
783 my $trial_id = $args->{trial_id};
784 my $protocol_id = $args->{genotyping_protocol_id};
786 if ( !$protocol_id ) {
787 my $protocol_detail = $self->protocol_detail();
788 $protocol_id = $protocol_detail->{protocol_id};
791 my $geno_search = CXGN::Genotype::Search->new(
793 bcs_schema => $self->schema(),
794 people_schema => $self->people_schema,
795 trial_list => [$trial_id],
796 protocol_id_list => [$protocol_id],
797 genotypeprop_hash_select => ['DS'],
798 protocolprop_top_key_select => [],
799 protocolprop_top_key_select => [],
800 return_only_first_genotypeprop_for_stock => 1,
804 $geno_search->init_genotype_iterator();
805 return $geno_search;
809 sub structure_genotype_data {
810 my ( $self, $dataref, $markers, $headers ) = @_;
812 my $geno_data;
814 if ($dataref) {
815 my $geno_hash = $dataref->{selected_genotype_hash};
817 if ($headers ) {
818 my $header_markers = $self->create_genotype_dataset_headers($markers);
819 $geno_data = "\t" . $header_markers. "\n";
823 $geno_data .= $dataref->{germplasmName} . "\t";
825 $geno_data .= ${ $self->create_genotype_row( $markers, $geno_hash ) };
826 $geno_data .= "\n";
829 return \$geno_data;
833 sub genotypes_list_genotype_data {
834 my ( $self, $genotypes_ids, $protocol_id ) = @_;
836 if ( !$protocol_id ) {
837 my $protocol_detail = $self->protocol_detail() if !$protocol_id;
838 $protocol_id = $protocol_detail->{protocol_id};
841 my $geno_search = CXGN::Genotype::Search->new(
842 bcs_schema => $self->schema(),
843 people_schema => $self->people_schema,
844 accession_list => $genotypes_ids,
845 protocol_id_list => [$protocol_id],
846 genotypeprop_hash_select => ['DS'],
847 protocolprop_top_key_select => [],
848 protocolprop_top_key_select => [],
849 return_only_first_genotypeprop_for_stock => 1,
853 $geno_search->init_genotype_iterator();
854 return $geno_search;
858 sub project_genotypes_rs {
859 my ( $self, $project_id ) = @_;
861 my $pr_genotypes_rs =
862 $self->schema->resultset("Project::Project")
863 ->search( { 'me.project_id' => $project_id } )
864 ->search_related('nd_experiment_projects')
865 ->search_related('nd_experiment')->search_related('nd_experiment_stocks')
866 ->search_related('stock')->search_related('stock_relationship_subjects')
867 ->search_related(
868 'object',
871 select => ['object.uniquename'],
872 distinct => 1
876 return $pr_genotypes_rs;
880 sub genotypes_nd_experiment_ids_rs {
881 my ( $self, $genotypes_ids ) = @_;
883 my $protocol = $self->genotyping_protocol();
885 my $nd_experiment_rs =
886 $self->schema->resultset("NaturalDiversity::NdExperimentStock")->search(
888 'me.stock_id' => { -in => $genotypes_ids },
889 'nd_protocol.name' => { 'ilike' => $protocol }
891 )->search_related('nd_experiment')
892 ->search_related('nd_experiment_protocols')->search_related(
893 'nd_protocol',
896 select => ['me.nd_experiment_id'],
897 as => ['nd_experiment_id'],
898 distinct => 1
902 return $nd_experiment_rs;
906 sub project_genotype_data_rs {
907 my ( $self, $project_id ) = @_;
909 my $trial = CXGN::Trial->new(
910 { 'bcs_schema' => $self->schema, 'trial_id' => $project_id } );
911 my $trial_accessions = $trial->get_accessions();
913 my @accessions;
915 foreach my $st (@$trial_accessions) {
916 push @accessions, $st->{stock_id};
919 my $genotype_rs = $self->accessions_list_genotypes_rs( \@accessions );
921 return $genotype_rs;
925 sub individual_stock_genotypes_rs {
926 my ( $self, $stock_rs ) = @_;
928 my $stock_id = $stock_rs->first()->stock_id;
930 my $nd_exp_rs = $self->genotypes_nd_experiment_ids_rs( [$stock_id] );
932 my @nd_exp_ids;
934 while ( my $row = $nd_exp_rs->next ) {
935 push @nd_exp_ids, $row->get_column('nd_experiment_id');
938 my $genotype_rs =
939 $stock_rs->search_related('nd_experiment_stocks')
940 ->search_related('nd_experiment')
941 ->search_related('nd_experiment_genotypes')->search_related('genotype')
942 ->search_related('genotypeprops')->search_related(
943 'type',
945 'type.name' => { 'ilike' => 'snp genotyping' },
946 'nd_experiment_genotypes.nd_experiment_id' =>
947 { -in => \@nd_exp_ids }
950 select => [
951 qw / me.stock_id me.uniquename genotypeprops.genotypeprop_id genotypeprops.value /
953 as => [qw / stock_id stock_name genotypeprop_id value/]
957 return $genotype_rs;
961 sub accessions_list_genotypes_rs {
962 my ( $self, $genotypes_ids ) = @_;
964 my $protocol = $self->genotyping_protocol();
965 my $genotype_rs =
966 $self->schema->resultset('NaturalDiversity::NdExperiment')->search(
968 'nd_protocol.name' => $protocol,
969 'stock.stock_id' => { -in => $genotypes_ids },
970 'type.name' => 'snp genotyping',
971 'cv.name' => 'genotype_property',
974 join => [
976 'nd_experiment_genotypes' => {
977 'genotype' => { 'genotypeprops' => { 'type' => 'cv' } }
980 { 'nd_experiment_protocols' => 'nd_protocol' },
981 { 'nd_experiment_stocks' => 'stock' }
984 select => [
985 qw / stock.stock_id stock.uniquename genotypeprops.genotypeprop_id genotypeprops.value /
987 as => [qw / stock_id stock_name genotypeprop_id value/],
988 distinct => 1,
992 return $genotype_rs;
996 sub get_stocks_rs {
997 my ( $self, $stock_names ) = @_;
999 my $stocks_rs = $self->schema->resultset("Stock::Stock")->search(
1000 { 'me.uniquename' => { -in => $stock_names } },
1002 select => [ 'me.stock_id', 'me.uniquename' ],
1003 as => [ 'stock_id', 'uniquename' ],
1004 distinct => 1,
1008 return $stocks_rs;
1012 sub genotyping_trials_rs {
1013 my $self = shift;
1015 my $geno_pr_rs = $self->schema->resultset("Project::Project")->search(
1017 "genotypeprops.value" => { "!=", undef },
1018 'type.name' => { 'ilike' => 'snp genotyping' }
1020 )->search_related('nd_experiment_projects')
1021 ->search_related('nd_experiment')->search_related('nd_experiment_stocks')
1022 ->search_related('stock')->search_related('nd_experiment_stocks')
1023 ->search_related('nd_experiment')
1024 ->search_related('nd_experiment_genotypes')->search_related('genotype')
1025 ->search_related('genotypeprops')->search_related(
1026 'type',
1030 select => [qw / me.project_id me.name /],
1031 as => [qw / project_id project_name /],
1032 distinct => [qw / me.project_id/],
1033 order_by =>
1034 'CASE WHEN me.name ~ \'^[0-9]+\' THEN 1 ELSE 0 END, me.name',
1039 return $geno_pr_rs;
1043 sub prediction_genotypes_rs {
1044 my ( $self, $pr_id ) = @_;
1046 my $genotypes_rs = $self->project_genotype_data_rs($pr_id);
1048 return $genotypes_rs;
1052 sub extract_project_markers {
1053 my ( $self, $geno_row ) = @_;
1055 my $markers;
1057 my $genotype_json = $geno_row->get_column('value');
1058 my $genotype_hash = JSON::Any->decode($genotype_json);
1059 my @markers = keys %$genotype_hash;
1061 foreach my $marker (@markers) {
1062 $markers .= $marker;
1063 $markers .= "\t" unless $marker eq $markers[-1];
1066 return $markers;
1069 sub get_dataset_markers {
1070 my ( $self, $geno_hash ) = @_;
1072 my @markers = keys %$geno_hash;
1074 return \@markers;
1078 sub create_genotype_dataset_headers {
1079 my ( $self, $markers ) = @_;
1081 my $headers = join( "\t", @$markers );
1083 return $headers;
1086 sub create_genotype_row {
1087 my ( $self, $markers, $genotype_hash ) = @_;
1089 my $geno_values;
1091 foreach my $marker (@$markers) {
1092 no warnings 'uninitialized';
1094 my $dosage = $genotype_hash->{$marker}->{'DS'};
1095 $geno_values .= $self->round_allele_dosage_values($dosage);
1096 $geno_values .= "\t" unless $marker eq $markers->[-1];
1099 return \$geno_values;
1103 sub round_allele_dosage_values {
1104 my ( $self, $geno_values ) = @_;
1106 my $round = Math::Round::Var->new(0);
1108 $geno_values =
1109 $geno_values =~ /\d+/g
1110 ? $round->round($geno_values)
1111 : $geno_values;
1113 return $geno_values;
1116 sub stock_genotype_values {
1117 my ( $self, $header_markers, $geno_row ) = @_;
1119 my $json_values = $geno_row->get_column('value');
1120 my $values = JSON::Any->decode($json_values);
1122 my $stock_name = $geno_row->get_column('stock_name');
1124 my $geno_values = $stock_name . "\t";
1126 foreach my $marker (@$header_markers) {
1127 no warnings 'uninitialized';
1129 my $genotype = $values->{$marker};
1130 $geno_values .= $genotype;
1131 $geno_values .= "\t" unless $marker eq $header_markers->[-1];
1134 $geno_values .= "\n";
1136 return $geno_values;
1139 sub prediction_pops {
1140 my ( $self, $training_pop_id ) = @_;
1142 my @tr_pop_markers;
1143 $self->context->stash->{get_selection_populations} = 1;
1145 if ( $training_pop_id =~ /^\d+$/ ) {
1146 my $dir = $self->context->stash->{solgs_cache_dir};
1147 opendir my $dh, $dir or die "can't open $dir: $!\n";
1149 my ($geno_file) =
1150 grep { /genotype_data_${training_pop_id}/ && -f "$dir/$_" }
1151 readdir($dh);
1152 closedir $dh;
1154 $geno_file = catfile( $dir, $geno_file );
1155 open my $fh, "<", $geno_file or die "can't open genotype file: $!";
1157 my $markers = <$fh>;
1158 chomp($markers);
1160 $fh->close;
1162 @tr_pop_markers = split( /\t/, $markers );
1163 shift(@tr_pop_markers);
1165 elsif ( $training_pop_id =~ /list/ ) {
1167 # my $user_id = $self->context->user->id;
1169 my $dir = $self->context->stash->{solgs_lists_dir};
1170 opendir my $dh, $dir or die "can't open $dir: $!\n";
1172 my ($geno_file) =
1173 grep { /genotype_data_${training_pop_id}/ && -f "$dir/$_" }
1174 readdir($dh);
1175 closedir $dh;
1177 $geno_file = catfile( $dir, $geno_file );
1178 open my $fh, "<", $geno_file or die "can't open genotype file: $!";
1180 my $markers = <$fh>;
1181 chomp($markers);
1183 $fh->close;
1185 @tr_pop_markers = split( /\t/, $markers );
1186 shift(@tr_pop_markers);
1189 my @sample_pred_projects;
1190 my $cnt = 0;
1191 my $projects_rs = $self->genotyping_trials_rs();
1192 my $count = $projects_rs->count;
1194 while ( my $row = $projects_rs->next ) {
1195 my $project_id = $row->get_column('project_id');
1196 if ( $project_id && $training_pop_id != $project_id ) {
1197 my $pop_type = $self->get_population_type($project_id);
1199 if ( $pop_type !~ /training population/ ) {
1200 my $pred_marker_cnt =
1201 $self->get_project_genotypeprop($project_id);
1202 $pred_marker_cnt = $pred_marker_cnt->{'marker_count'};
1204 my $potential_selection;
1206 if ($pred_marker_cnt) {
1207 if ( scalar(@tr_pop_markers) / $pred_marker_cnt > 0.5 ) {
1208 $potential_selection = 'yes';
1212 if ( !$pred_marker_cnt
1213 || ( $pred_marker_cnt && $potential_selection ) )
1215 my $stock_genotype_rs =
1216 $self->prediction_genotypes_rs($project_id);
1217 my $stocks_count = $stock_genotype_rs->count;
1218 my $first_geno = $stock_genotype_rs->single;
1220 if ( $stocks_count > 10 && $first_geno ) {
1221 my $pop_prop = {
1222 'project_id' => $project_id,
1223 'population type' => 'selection population',
1226 $self->set_population_type($pop_prop);
1228 my $obj_name = $first_geno->get_column('stock_name');
1229 my $stock_rs = $self->search_stock($obj_name);
1230 $stock_genotype_rs =
1231 $self->individual_stock_genotypes_rs($stock_rs);
1233 my $markers =
1234 $self->extract_project_markers(
1235 $stock_genotype_rs->first );
1237 if ($markers) {
1238 my @pred_pop_markers = split( /\t/, $markers );
1240 unless ($pred_marker_cnt) {
1241 my $genoprop = {
1242 'project_id' => $project_id,
1243 'marker_count' => scalar(@pred_pop_markers)
1245 $self->set_project_genotypeprop($genoprop);
1248 print STDERR
1249 "\ncheck if prediction populations are genotyped using the same
1250 set of markers as for the training population : "
1251 . scalar(@pred_pop_markers) . ' vs '
1252 . scalar(@tr_pop_markers) . "\n";
1254 my $common_markers = scalar(
1255 intersect( @pred_pop_markers, @tr_pop_markers )
1257 my $similarity =
1258 $common_markers / scalar(@tr_pop_markers);
1260 if ( $similarity > 0.5 ) {
1261 $cnt++;
1262 push @sample_pred_projects, $project_id;
1270 last if $cnt == 5;
1273 return \@sample_pred_projects;
1277 sub plots_list_phenotype_data {
1278 my ( $self, $plots_ids ) = @_;
1280 my $phenotypes_search = CXGN::Phenotypes::PhenotypeMatrix->new(
1281 bcs_schema => $self->schema,
1282 data_level => 'plot',
1283 search_type => 'MaterializedViewTable',
1284 plot_list => $plots_ids,
1287 my @data = $phenotypes_search->get_phenotype_matrix();
1288 my $clean_data = $self->structure_phenotype_data( \@data );
1290 return \$clean_data;
1294 sub trial_traits {
1295 my ( $self, $pr_id ) = @_;
1297 my $trial = CXGN::Trial->new(
1299 bcs_schema => $self->schema,
1300 trial_id => $pr_id
1304 return $trial->get_traits_assayed();
1308 sub project_trait_phenotype_data_rs {
1309 my ( $self, $project_id, $trait_id ) = @_;
1311 my $rs = $self->schema->resultset("Stock::Stock")->search(
1313 'observable.cvterm_id' => $trait_id,
1314 'project.project_id' => $project_id,
1317 join => [
1319 nd_experiment_stocks => {
1320 nd_experiment => {
1321 nd_experiment_phenotypes => {
1322 phenotype => 'observable'
1324 nd_experiment_projects => 'project',
1330 select => [
1331 qw/ me.stock_id me.uniquename phenotype.value observable.name observable.cvterm_id project.description project.project_id /
1333 as => [
1334 qw/ stock_id uniquename value observable observable_id project_description project_id /
1340 return $rs;
1344 sub get_plot_phenotype_rs {
1345 my ( $self, $plot_id, $trait_id ) = @_;
1347 my $pheno_rs = $self->schema->resultset("Phenotype::Phenotype")->search(
1349 'me.uniquename' => { "iLIKE" => "Stock: $plot_id, %" },
1352 join => 'observable',
1353 '+select' => [qw / observable.name /],
1354 '+as' => [qw / cvterm_name /],
1355 distinct => 1,
1356 order_by => ['observable.name']
1360 return $pheno_rs;
1363 sub get_plot_phenotype_data {
1364 my ( $self, $plot_id ) = @_;
1366 my $project_desc = $self->context->stash->{project_description};
1367 my $plot_uniquename = $self->context->stash->{plot_uniquename};
1369 my $object_rs = $self->map_subject_to_object($plot_id);
1370 my ( $object_name, $object_id );
1372 while ( my $ob_r = $object_rs->next ) {
1373 $object_name = $ob_r->name;
1374 $object_id = $ob_r->stock_id;
1377 my $uniquename = $project_desc . "|" . $plot_uniquename;
1379 my $block = 'NA';
1380 my $replicate = 'NA';
1382 my $design = $self->context->stash->{design};
1383 $design = $design ? $design : 'NA';
1385 my $block_rs = $self->search_plotprop( $plot_id, 'block' );
1386 if ( $block_rs->next )
1389 $block = $block_rs->single->value();
1392 my $replicate_rs = $self->search_plotprop( $plot_id, 'replicate' );
1393 if ( $replicate_rs->next ) {
1394 $replicate = $replicate_rs->single->value();
1397 my $dh = " ";
1398 my $d =
1399 "$uniquename\t$object_name\t$object_id\t$plot_id\t$plot_uniquename\t$design\t$block\t$replicate";
1401 my $plot_pheno_rs = $self->get_plot_phenotype_rs($plot_id);
1402 my $cnt = 0;
1404 while ( my $pl_r = $plot_pheno_rs->next ) {
1405 my $trait = $pl_r->get_column('cvterm_name');
1406 my $value = $pl_r->value;
1408 $dh .= "\t" . $trait;
1409 $d .= "\t" . $value;
1411 $cnt++;
1414 return $d, $dh;
1417 sub project_phenotype_data_rs {
1418 my ( $self, $project_id ) = @_;
1420 my $rs = $self->schema->resultset("Stock::Stock")->search(
1422 'observable.name' => { '!=', undef },
1423 'project.project_id' => $project_id,
1426 join => [
1428 nd_experiment_stocks => {
1429 nd_experiment => {
1430 nd_experiment_phenotypes => {
1431 phenotype => 'observable'
1433 nd_experiment_projects => 'project',
1438 select => [
1439 qw/ me.stock_id me.uniquename phenotype.value observable.name observable.cvterm_id project.description project.project_id /
1441 as => [
1442 qw/ stock_id uniquename value observable observable_id project_description project_id /
1445 order_by => ['observable.name'],
1449 return $rs;
1453 sub plots_list_phenotype_data_rs {
1454 my ( $self, $plots ) = @_;
1456 my $rs = $self->schema->resultset("Stock::Stock")->search(
1458 'observable.name' => { '!=', undef },
1459 'me.uniquename' => { -in => $plots },
1462 join => [
1464 nd_experiment_stocks => {
1465 nd_experiment => {
1466 nd_experiment_phenotypes => {
1467 phenotype => 'observable'
1469 nd_experiment_projects => 'project',
1474 select => [
1475 qw/ me.stock_id me.uniquename phenotype.value observable.name observable.cvterm_id project.project_id project.name /
1477 as => [
1478 qw/ germplasmDbId germplasmName value observable observable_id studyDbId studyName /
1481 order_by => ['observable.name'],
1485 return $rs;
1489 sub stock_phenotype_data_rs {
1490 my $self = shift;
1491 my $stock_rs = shift;
1493 my $stock_id;
1494 if ( $stock_rs->first ) {
1495 $stock_id = $stock_rs->first->stock_id;
1498 die "Can't get stock phenotype data with out stock_id" if !$stock_id;
1500 my $rs = $self->schema->resultset("Stock::Stock")->search(
1502 'observable.name' => { '!=', undef },
1503 'me.stock_id' => $stock_id,
1506 join => [
1508 nd_experiment_stocks => {
1509 nd_experiment => {
1510 nd_experiment_phenotypes => {
1511 phenotype => 'observable'
1513 nd_experiment_projects => 'project',
1518 select => [
1519 qw/ me.stock_id me.uniquename phenotype.value observable.name observable.cvterm_id project.description project.project_id/
1521 as => [
1522 qw/ stock_id uniquename value observable observable_id project_description project_id /
1525 order_by => ['observable.name'],
1529 return $rs;
1532 sub phenotype_data {
1533 my ( $self, $project_id ) = @_;
1535 my $phenotypes_search = CXGN::Phenotypes::PhenotypeMatrix->new(
1536 bcs_schema => $self->schema,
1537 search_type => 'Native',
1538 trial_list => [$project_id],
1539 data_level => 'plot',
1542 my @data = $phenotypes_search->get_phenotype_matrix();
1544 my $clean_data = $self->structure_phenotype_data( \@data );
1546 return \$clean_data;
1550 sub project_trait_phenotype_data {
1551 my ( $self, $pop_id, $trait_id ) = @_;
1553 my $data;
1554 if ( $pop_id && $trait_id ) {
1555 my $phenotypes =
1556 $self->project_trait_phenotype_data_rs( $pop_id, $trait_id );
1557 $data = $self->structure_phenotype_data($phenotypes);
1560 return $data;
1563 sub structure_phenotype_data {
1564 my ( $self, $data ) = @_;
1566 my $round = Math::Round::Var->new(0.001);
1568 my $formatted_data;
1570 no warnings 'uninitialized';
1572 for ( my $i = 0 ; $i < @$data ; $i++ ) {
1573 my $row = $data->[$i];
1574 $row = join( "\t", @$row );
1575 $formatted_data .= $row . "\n";
1578 return $formatted_data;
1581 sub trial_metadata {
1582 my ($self) = @_;
1584 my @headers = (
1585 'studyYear',
1586 'programDbId',
1587 'programName',
1588 'programDescription',
1589 'studyDbId',
1590 'studyName',
1591 'studyDescription',
1592 'studyDesign',
1593 'plotWidth',
1594 'plotLength',
1595 'fieldSize',
1596 'fieldTrialIsPlannedToBeGenotyped',
1597 'fieldTrialIsPlannedToCross',
1598 'plantingDate',
1599 'harvestDate',
1600 'locationDbId',
1601 'locationName',
1602 'germplasmDbId',
1603 'germplasmName',
1604 'germplasmSynonyms',
1605 'observationLevel',
1606 'observationUnitDbId',
1607 'observationUnitName',
1608 'replicate',
1609 'blockNumber',
1610 'plotNumber',
1611 'rowNumber',
1612 'colNumber',
1613 'entryType',
1614 'plantNumber',
1615 'plantedSeedlotStockDbId',
1616 'plantedSeedlotStockUniquename',
1617 'plantedSeedlotCurrentCount',
1618 'plantedSeedlotCurrentWeightGram',
1619 'plantedSeedlotBoxName',
1620 'plantedSeedlotTransactionCount',
1621 'plantedSeedlotTransactionWeight',
1622 'plantedSeedlotTransactionDescription',
1623 'availableGermplasmSeedlotUniquenames',
1624 'notes'
1627 return \@headers;
1631 sub structure_plots_list_phenotype_data {
1632 my $self = shift;
1633 my $phenotypes = shift;
1635 my $phen_hashref = {}; #hashref of hashes for the phenotype data
1637 my %cvterms; #hash for unique cvterms
1638 my $replicate = 1;
1639 my $cvterm_name;
1641 no warnings 'uninitialized';
1643 my $trial_id;
1644 my $project;
1646 my $round = Math::Round::Var->new(0.001);
1648 while ( my $r = $phenotypes->next ) {
1649 my $observable = $r->get_column('observable');
1650 next if !$observable;
1652 if ( $cvterm_name eq $observable ) { $replicate++; }
1653 else { $replicate = 1; }
1654 $cvterm_name = $observable;
1656 $project = $r->get_column('studyName');
1658 $trial_id = $r->get_column('studyDbId') if $replicate == 1;
1660 my $hash_key = $r->get_column('germplasmName');
1662 $phen_hashref->{$hash_key}{$observable} = $r->get_column('value');
1663 $phen_hashref->{$hash_key}{germplasmDbId} =
1664 $r->get_column('germplasmDbId');
1665 $phen_hashref->{$hash_key}{germplasmName} =
1666 $r->get_column('germplasmName');
1667 $phen_hashref->{$hash_key}{studyName} = $r->get_column('studyName');
1668 $cvterms{$observable} = 'NA';
1672 my $d;
1674 if ( keys %cvterms ) {
1675 $d =
1676 "germplasmName\tgermplasmDbId\tstudyName\tstudyYear\tlocationName\tstudyDesign\tblockNumber\treplicate";
1678 foreach
1679 my $term_name ( sort { $cvterms{$a} cmp $cvterms{$b} } keys %cvterms )
1681 $d .= "\t" . $term_name;
1684 $d .= "\n";
1686 my @project_genotypes;
1688 foreach my $key ( sort keys %$phen_hashref ) {
1689 my $subject_id = $phen_hashref->{$key}{germplasmDbId};
1690 my $stock_object_row =
1691 $self->map_subject_to_object($subject_id)->single;
1693 my ( $object_name, $object_id );
1694 if ($stock_object_row) {
1695 $object_name = $stock_object_row->uniquename;
1696 $object_id = $stock_object_row->stock_id;
1698 push @project_genotypes, $object_name;
1701 $d .=
1702 $object_name . "\t"
1703 . $object_id . "\t"
1704 . $phen_hashref->{$key}{studyName};
1706 my $location_name = 'NA';
1707 my $study_year = 'NA';
1708 my $design = 'NA';
1709 my $block = 'NA';
1710 my $replicate = 'NA';
1712 my $design_rs = $self->experimental_design($trial_id);
1714 if ( $design_rs->next ) {
1715 $design = $design_rs->first->value();
1718 my $block_rs = $self->search_plotprop( $subject_id, 'block' );
1719 if ( $block_rs->next ) {
1720 $block = $block_rs->first->value();
1723 my $replicate_rs =
1724 $self->search_plotprop( $subject_id, 'replicate' );
1725 if ( $replicate_rs->next ) {
1726 $replicate = $replicate_rs->first->value();
1729 $d .= "\t"
1730 . $study_year . "\t"
1731 . $location_name . "\t"
1732 . $design . "\t"
1733 . $replicate . "\t"
1734 . $block;
1736 foreach my $term_name (
1737 sort { $cvterms{$a} cmp $cvterms{$b} }
1738 keys %cvterms
1741 my $val = $phen_hashref->{$key}{$term_name};
1742 if ( looks_like_number($val) ) {
1743 $val = $round->round($val);
1745 else {
1746 $val = "NA";
1749 $d .= "\t" . $val;
1751 $d .= "\n";
1754 # @project_genotypes = uniq(@project_genotypes);
1755 # $self->context->stash->{project_genotypes} = \@project_genotypes;
1758 return $d;
1761 =head2 phenotypes_by_trait
1763 Usage: $self->phenotypes_by_trait($phenotype_rs , { %args } )
1764 Desc: generate a report of phenotype values by trait name/accession
1765 Args: an arrayref of L<Bio::Chado::Schema::Result::Phenotype::Phenotype> ResultSets
1766 [optional] list of args to filter the report. Currently supported args are
1768 Ret: arrayref of tab delimited data
1770 =cut
1772 sub phenotypes_by_trait {
1773 my $self = shift;
1774 my $phenotypes = shift;
1776 my $phen_hashref = {}; #hashref of hashes for the phenotype data
1778 my %cvterms; #hash for unique cvterms
1779 my $replicate = 1;
1780 my $cvterm_name;
1781 my $cnt = 0;
1783 my $trial_id;
1785 no warnings 'uninitialized';
1787 my $round = Math::Round::Var->new(0.001);
1789 foreach my $rs (@$phenotypes) {
1790 $cnt++;
1791 while ( my $r = $rs->next ) {
1792 my $observable = $r->get_column('observable');
1793 next if !$observable;
1795 if ( $cvterm_name eq $observable ) { $replicate++; }
1796 else { $replicate = 1; }
1797 $cvterm_name = $observable;
1799 my $project = $r->get_column('project_description');
1800 $trial_id = $r->get_column('project_id') if $replicate == 1;
1801 my $hash_key = $r->get_column('uniquename');
1803 # $phen_hashref->{$hash_key}{accession} = $db_name . ":" . $accession ;
1804 $phen_hashref->{$hash_key}{$observable} = $r->get_column('value');
1805 $phen_hashref->{$hash_key}{stock_id} = $r->get_column('stock_id');
1806 $phen_hashref->{$hash_key}{stock_name} =
1807 $r->get_column('uniquename');
1808 $cvterms{$observable} = 'NA';
1812 my @data;
1813 my $d =
1814 "uniquename\tobject_name\tobject_id\tstock_id\tstock_name\tdesign\tblock\treplicate";
1815 foreach
1816 my $term_name ( sort { $cvterms{$a} cmp $cvterms{$b} } keys %cvterms )
1817 { # sort ontology terms
1818 # my $ontology_id = $cvterms{$term_name};
1819 # $d .= "\t" . $ontology_id . "|" . $term_name;
1820 $d .= "\t" . $term_name;
1822 $d .= "\n";
1824 foreach my $key ( sort keys %$phen_hashref ) {
1826 #print the unique key (row header)
1827 # print some more columns with metadata
1828 # print the value by cvterm name
1830 my $subject_id = $phen_hashref->{$key}{stock_id};
1831 my $stock_object_row =
1832 $self->map_subject_to_object($subject_id)->single;
1833 my $object_name = $stock_object_row->uniquename;
1834 my $object_id = $stock_object_row->stock_id;
1836 $d .=
1837 $key . "\t"
1838 . $object_name . "\t"
1839 . $object_id . "\t"
1840 . $phen_hashref->{$key}{stock_id} . "\t"
1841 . $phen_hashref->{$key}{stock_name};
1843 my $block = 'NA';
1844 my $replicate = 'NA';
1845 my $design = 'NA';
1847 my $design_rs = $self->experimental_design($trial_id);
1849 if ( $design_rs->next ) {
1850 $design = $design_rs->first->value();
1853 my $block_rs = $self->search_plotprop( $subject_id, 'block' );
1854 if ( $block_rs->next ) {
1855 $block = $block_rs->first->value();
1858 my $replicate_rs = $self->search_plotprop( $subject_id, 'replicate' );
1859 if ( $replicate_rs->next ) {
1860 $replicate = $replicate_rs->first->value();
1863 $d .= "\t" . $design . "\t" . $block . "\t" . $replicate;
1865 foreach
1866 my $term_name ( sort { $cvterms{$a} cmp $cvterms{$b} } keys %cvterms )
1868 my $val = $phen_hashref->{$key}{$term_name};
1870 if ( looks_like_number($val) ) {
1871 $val = $round->round($val);
1873 else {
1874 $val = "NA";
1877 $d .= "\t" . $val;
1878 $d .= "\t" . $phen_hashref->{$key}{$term_name};
1881 $d .= "\n";
1884 $d = undef if $d eq '';
1886 return $d;
1889 sub stock_projects_rs {
1890 my ( $self, $stock_rs ) = @_;
1892 my $project_rs =
1893 $stock_rs->search_related('nd_experiment_stocks')
1894 ->search_related('nd_experiment')
1895 ->search_related('nd_experiment_projects')->search_related(
1896 'project',
1899 distinct => 1,
1903 return $project_rs;
1907 sub project_subject_stocks_rs {
1908 my ( $self, $project_id ) = @_;
1910 my $stock_rs =
1911 $self->schema->resultset("Project::Project")
1912 ->search( { 'me.project_id' => $project_id } )
1913 ->search_related('nd_experiment_projects')
1914 ->search_related('nd_experiment')->search_related('nd_experiment_stocks')
1915 ->search_related('stock')->search_related('stock_relationship_subjects')
1916 ->search_related(
1917 'subject',
1922 return $stock_rs;
1925 sub stocks_object_rs {
1926 my ( $self, $stock_subj_rs ) = @_;
1928 my $stock_obj_rs =
1929 $stock_subj_rs->search_related('stock_relationship_subjects')
1930 ->search_related(
1931 'object',
1934 '+select' => [qw /me.project_id me.name/],
1935 '+as' => [qw /project_id project_name/]
1939 return $stock_obj_rs;
1942 sub map_subject_to_object {
1943 my ( $self, $stock_id ) = @_;
1945 my $stock_obj_rs =
1946 $self->schema->resultset("Stock::Stock")
1947 ->search( { 'me.stock_id' => $stock_id } )
1948 ->search_related('stock_relationship_subjects')->search_related('object');
1950 return $stock_obj_rs;
1953 sub get_genotypes_from_plots {
1954 my ( $self, $plots ) = @_;
1956 my $genotypes_rs =
1957 $self->schema->resultset("Stock::Stock")
1958 ->search( { 'me.uniquename' => { -in => $plots } } )
1959 ->search_related('stock_relationship_subjects')->search_related('object');
1961 return $genotypes_rs;
1964 sub trial_breeding_program_id {
1965 my ( $self, $trial_id ) = @_;
1967 my $type_id =
1968 $self->schema->resultset('Cv::Cvterm')
1969 ->search( { 'name' => 'breeding_program_trial_relationship' } )
1970 ->single->id;
1972 my $breeding_id =
1973 $self->schema->resultset("Project::ProjectRelationship")
1974 ->search(
1975 { 'me.subject_project_id' => $trial_id, 'me.type_id' => $type_id } )
1976 ->single->object_project_id;
1978 return $breeding_id;
1981 sub get_project_genotyping_markers {
1982 my ( $self, $pr_id ) = @_;
1984 my $stock_genotype_rs = $self->project_genotype_data_rs($pr_id);
1986 my $markers;
1988 if ( $stock_genotype_rs->first ) {
1989 $markers = $self->extract_project_markers( $stock_genotype_rs->first );
1992 return $markers;
1996 sub genotyping_protocol {
1997 my ( $self, $protocol ) = @_;
1999 unless ($protocol) {
2000 $protocol = $self->context->config->{default_genotyping_protocol};
2003 return $protocol;
2007 sub protocol_detail {
2008 my ( $self, $protocol ) = @_;
2010 # unless ($protocol)
2012 # $protocol = $self->context->config->{default_genotyping_protocol};
2015 my $where;
2016 if ( $protocol =~ /[A-Za-z]/ ) {
2017 $where = 'WHERE name = ?';
2019 else {
2020 $where = 'WHERE nd_protocol_id = ?';
2023 my $q =
2024 'SELECT nd_protocol_id, name, description FROM nd_protocol ' . $where;
2025 my $sth = $self->schema->storage->dbh->prepare($q);
2026 $sth->execute($protocol);
2027 my ( $protocol_id, $name, $desc ) = $sth->fetchrow_array();
2029 return {
2030 'protocol_id' => $protocol_id,
2031 'name' => $name,
2032 'description' => $desc
2037 sub get_all_genotyping_protocols {
2038 my ( $self, $trial_id ) = @_;
2040 my $where = ' WHERE genotyping_protocol_id > 0';
2041 my $q;
2043 if ($trial_id) {
2044 $where = ' WHERE trial_id = ?';
2045 $q = 'SELECT distinct(genotyping_protocol_id)
2046 FROM genotyping_protocolsXtrials' . $where;
2048 else {
2049 $q = 'SELECT distinct(genotyping_protocol_id)
2050 FROM genotyping_protocols' . $where;
2053 my $sth = $self->schema->storage->dbh->prepare($q);
2055 $trial_id ? $sth->execute($trial_id) : $sth->execute();
2057 my @protocol_ids;
2059 while ( my $protocol_id = $sth->fetchrow_array() ) {
2060 push @protocol_ids, $protocol_id;
2063 return \@protocol_ids;
2066 sub get_genotypes_from_dataset {
2067 my ( $self, $dataset_id ) = @_;
2069 my $data = $self->get_dataset_data($dataset_id);
2070 my @accessions_ids;
2072 if ( $data->{categories}->{accessions}->[0] ) {
2073 @accessions_ids = @{$data->{categories}->{accessions}};
2075 else {
2076 my $dataset = CXGN::Dataset->new(
2078 people_schema => $self->people_schema,
2079 schema => $self->schema,
2080 sp_dataset_id => $dataset_id
2084 my $accessions = $dataset->retrieve_accessions();
2085 if ($accessions->[0]) {
2086 for (my $i=0; $i < scalar(@$accessions); $i++) {
2087 push @accessions_ids, $accessions->[$i][0];
2092 @accessions_ids = uniq(@accessions_ids) if @accessions_ids;
2094 return \@accessions_ids;
2097 sub get_dataset_data {
2098 my ( $self, $dataset_id ) = @_;
2100 my $dataset = CXGN::Dataset->new(
2102 people_schema => $self->people_schema,
2103 schema => $self->schema,
2104 sp_dataset_id => $dataset_id
2108 my $dataset_data = $dataset->get_dataset_data();
2110 return $dataset_data;
2113 sub get_dataset_plots_list {
2114 my ( $self, $dataset_id ) = @_;
2116 my $dataset = CXGN::Dataset->new(
2118 people_schema => $self->people_schema,
2119 schema => $self->schema,
2120 sp_dataset_id => $dataset_id
2124 my $plots = $dataset->retrieve_plots();
2126 return $plots;
2129 sub get_dataset_name {
2130 my ( $self, $dataset_id ) = @_;
2132 my $dataset = CXGN::Dataset->new(
2134 people_schema => $self->people_schema,
2135 schema => $self->schema,
2136 sp_dataset_id => $dataset_id
2140 return $dataset->name();
2143 sub get_dataset_owner {
2144 my ( $self, $dataset_id ) = @_;
2146 my $dataset = CXGN::Dataset->new(
2148 people_schema => $self->people_schema,
2149 schema => $self->schema,
2150 sp_dataset_id => $dataset_id
2154 return $dataset->sp_person_id();
2157 sub get_dataset_genotype_data {
2158 my ( $self, $dataset_id, $protocol_id ) = @_;
2160 my $protocol_detail = $self->protocol_detail($protocol_id);
2161 $protocol_id = $protocol_detail->{protocol_id};
2163 my $geno_search = CXGN::Genotype::Search->new(
2164 bcs_schema => $self->schema(),
2165 people_schema => $self->people_schema,
2166 sp_dataset_id => $dataset_id,
2167 protocol_id_list => [$protocol_id],
2168 genotypeprop_hash_select => ['DS'],
2169 protocolprop_top_key_select => [],
2170 protocolprop_top_key_select => [],
2171 return_only_first_genotypeprop_for_stock => 1,
2174 $geno_search->init_genotype_iterator();
2175 return $geno_search;
2179 __PACKAGE__->meta->make_immutable;
2181 #####
2183 #####