fixed get stocks functions
[sgn.git] / lib / CXGN / Project.pm
blob43c21dd28fffe50976aedbab3aeda434c7d0ebd1
2 =head1 NAME
4 CXGN::Project - helper class for projects
6 =head1 DESCRIPTION
8 CXGN::Project is the root object for information stored in the project table, such as trials, genotyping trials, breeding programs, folders, etc.
10 It should rarely be necessary to be instantiated on its own. Use the CXGN::Trial factory object to generate the appropriate object from a project_id.
12 =head1 SYNOPSYS
14 my $project = CXGN::Project->new( { bcs_schema => $schema, trial_id => $trial_id });
15 $trial->set_description("yield trial with promising varieties");
16 etc.
18 =head1 AUTHOR
20 Lukas Mueller <lam87@cornell.edu>
22 =head1 METHODS
24 =cut
26 package CXGN::Project;
28 use Moose;
30 use Data::Dumper;
31 use Try::Tiny;
32 use Data::Dumper;
33 use CXGN::Trial::Folder;
34 use CXGN::Trial::TrialLayout;
35 use CXGN::Trial::TrialLayoutDownload;
36 use SGN::Model::Cvterm;
37 use Time::Piece;
38 use Time::Seconds;
39 use CXGN::Calendar;
40 use JSON;
41 use File::Basename qw | basename dirname|;
43 =head2 accessor bcs_schema()
45 accessor for bcs_schema. Needs to be set when calling the constructor.
47 =cut
49 has 'bcs_schema' => (
50 isa => 'Bio::Chado::Schema',
51 is => 'rw',
52 required => 1,
55 has 'metadata_schema' => (
56 isa => 'CXGN::Metadata::Schema',
57 is => 'rw',
60 has 'phenome_schema' => (
61 isa => 'CXGN::Phenome::Schema',
62 is => 'rw',
65 has 'project_id' => (
66 isa => 'Maybe[Int]',
67 is => 'rw',
68 trigger => \&set_trial_id,
69 builder => 'get_trial_id',
72 has 'name' => (
73 isa => 'Str',
74 is => 'rw',
75 trigger => \&set_name,
76 builder => 'get_name',
77 lazy => 1,
80 has 'description' => (
81 isa => 'Maybe[Str]',
82 is => 'rw',
83 trigger => \&set_description,
84 builder => 'get_description',
85 lazy => 1,
88 has 'year' => (
89 isa => 'Maybe[Str]',
90 is => 'rw',
91 trigger => \&get_year,
92 builder => 'set_year',
93 lazy => 1,
96 sub BUILD {
97 my $self = shift;
98 my $args = shift;
100 print STDERR "BUILD CXGN::Project... with ".$args->{trial_id}."\n";
102 if (! $args->{description}) {
103 $args->{description} = "(No description provided)";
106 my $row = $self->bcs_schema()->resultset("Project::Project")->find( { project_id => $args->{trial_id} });
108 print STDERR "PROJECT ID = $args->{trial_id}\n";
109 if ($row){
110 $self->name( $row->name() );
113 if ($args->{trial_id} && ! $row) {
114 die "The trial ".$args->{trial_id}." does not exist - aborting.";
117 $row = $self->bcs_schema()->resultset("Project::Project")->find( { name => $args->{name } } );
120 if (! $args->{trial_id} && $row) {
121 die "A trial with the name $args->{name} already exists. Please choose another name.";
124 if (! $args->{trial_id} && ! $row) {
125 print STDERR "INSERTING A NEW ROW...\n";
127 my $new_row = $args->{bcs_schema}->resultset("Project::Project")->create( { name => $args->{name}, description => $args->{description} });
128 my $project_id = $new_row->project_id();
129 print STDERR "new project object has project id $project_id\n";
131 $self->set_trial_id($project_id);
134 if ($args->{trial_id} && $row) {
135 print STDERR "Existing project... populating object.\n";
136 $self->set_trial_id($args->{trial_id});
137 $self->name($args->{name});
138 $self->description($args->{description});
142 =head2 accessors get_trial_id()
144 Desc: get the trial id
146 =cut
148 has 'trial_id' => (isa => 'Int',
149 is => 'rw',
150 reader => 'get_trial_id',
151 writer => 'set_trial_id',
154 =head2 accessors get_layout(), set_layout()
156 Desc: set the layout object for this trial (CXGN::Trial::TrialLayout)
157 (This is populated automatically by the constructor)
159 =cut
161 has 'layout' => (isa => 'CXGN::Trial::TrialLayout::Phenotyping |
162 CXGN::Trial::TrialLayout::Genotyping |
163 CXGN::Trial::TrialLayout::Analysis',
164 is => 'rw',
165 reader => 'get_layout',
166 writer => 'set_layout',
167 predicate => 'has_layout',
168 lazy => 1,
169 default => sub { my $self = shift; $self->_get_layout(); }
172 sub _get_layout {
173 my $self = shift;
174 print STDERR "RETRIEVING LAYOUT...\n";
175 my $layout = CXGN::Trial::TrialLayout->new( { schema => $self->bcs_schema, trial_id => $self->get_trial_id(), experiment_type=>$self->get_cxgn_project_type()->{experiment_type} });
176 $self->set_layout($layout);
179 =head2 accessors get_cxgn_project_type()
181 get the CXGN::Project type e.g. field trial, analysis, genotyping trial, etc
183 =cut
185 sub get_cxgn_project_type {
186 my $self = shift;
188 my $analysis_metadata_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'analysis_metadata_json', 'project_property')->cvterm_id();
189 my $crossing_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'crossing_trial', 'project_type')->cvterm_id();
191 my $q = "SELECT projectprop.type_id, projectprop.value FROM project JOIN projectprop USING(project_id)";
192 my $h = $self->bcs_schema->storage->dbh->prepare($q);
193 $h->execute();
195 my $cxgn_project_type = 'field_trial_project';
196 my $plot_data_level = 'plot';
197 my $experiment_type = 'field_layout';
198 while (my ($prop, $propvalue) = $h->fetchrow_array()) {
199 if ($prop) {
200 if ($prop == $crossing_trial_cvterm_id) {
201 $cxgn_project_type = 'crossing_project';
203 if ($prop == $analysis_metadata_cvterm_id) {
204 $cxgn_project_type = 'analysis_project';
205 $plot_data_level = 'analysis_instance';
206 $experiment_type = 'analysis_experiment';
208 if ($propvalue) {
209 if ($propvalue eq "genotyping_plate") {
210 $cxgn_project_type = 'genotyping_plate_project';
211 $experiment_type = 'genotyping_layout';
213 if ($propvalue eq "treatment") {
214 $cxgn_project_type = 'management_factor_project';
216 if ($propvalue eq "genotype_data_project") {
217 $cxgn_project_type = 'genotyping_data_project';
219 if ($propvalue eq "drone_run") {
220 $cxgn_project_type = 'drone_run_project';
222 if ($propvalue eq "drone_run_band") {
223 $cxgn_project_type = 'drone_run_band_project';
228 return {
229 cxgn_project_type => $cxgn_project_type,
230 data_level => $plot_data_level,
231 experiment_type => $experiment_type
235 =head2 accessors get_year(), set_year()
237 getter/setter for the year property. The setter modifies the database.
239 =cut
241 sub get_year {
242 my $self = shift;
244 print STDERR "get_year()...\n";
246 if ($self->year()) { return $self->year(); }
248 my $type_id = $self->get_year_type_id();
250 my $rs = $self->bcs_schema->resultset('Project::Project')->search( { 'me.project_id' => $self->get_trial_id() })->search_related('projectprops', { type_id => $type_id } );
252 if ($rs->count() == 0) {
253 return undef;
255 else {
256 return $rs->first()->value();
261 sub set_year {
262 my $self = shift;
263 my $year = shift;
265 if (!$year) {
266 print STDERR "set_year(): No year provided, not setting.\n";
267 return;
270 print STDERR "set_year()... (with parameter $year)\n";
271 my $type_id = $self->get_year_type_id();
273 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find( { project_id => $self->get_trial_id(), type_id => $type_id });
275 if ($row) {
276 print STDERR "Updating year to $year...\n";
277 $row->value($year);
278 $row->update();
280 else {
281 print STDERR "inserting new year ($year)...\n";
282 $row = $self->bcs_schema->resultset('Project::Projectprop')->create(
284 type_id => $type_id,
285 value => $year,
286 project_id => $self->get_trial_id()
287 } );
288 $year = $row->value();
290 return $year;
293 =head2 accessors get_description(), set_description()
295 getter/setter for the description
297 =cut
299 sub get_description {
300 my $self = shift;
302 print STDERR "Get description for trial id ".$self->get_trial_id()."\n";
303 my $rs = $self->bcs_schema->resultset('Project::Project')->search( { project_id => $self->get_trial_id() });
305 return $rs->first()->description();
310 sub set_description {
311 my $self = shift;
312 my $description = shift;
314 my $row = $self->bcs_schema->resultset('Project::Project')->find( { project_id => $self->get_trial_id() });
316 #print STDERR "Setting new description $description for trial ".$self->get_trial_id()."\n";
318 $row->description($description);
320 $row->update();
325 =head2 function get_nd_experiment_id()
327 Usage: my $location = $trial->get_nd_experiment_id();
328 Desc: Every trial should have only a single nd_experiment entry of type 'field_layout'. This returns this nd_experiment_id for the trial.
329 Ret: $nd_experiment_id
330 Args:
331 Side Effects:
332 Example:
334 =cut
336 sub get_nd_experiment_id {
337 my $self = shift;
338 my $nd_experiment_field_layout_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'field_layout', 'experiment_type')->cvterm_id();
339 my $nd_experiment_genotyping_layout_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'genotyping_layout', 'experiment_type')->cvterm_id();
340 my $nd_experiment_rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperiment')->search(
341 { 'me.type_id' => [$nd_experiment_field_layout_type_id, $nd_experiment_genotyping_layout_type_id], 'project.project_id' => $self->get_trial_id },
342 { 'join' => {'nd_experiment_projects'=>'project'}}
344 if ($nd_experiment_rs->count > 1){
345 return {error => "A trial cannot have more than one nd_experiment entry of type field_layout. Please contact us."};
347 if ($nd_experiment_rs == 1){
348 return {success => 1, nd_experiment_id => $nd_experiment_rs->first->nd_experiment_id};
349 } else {
350 return {error => "This trial does not have an nd_experiment entry of type field_layout. Please contact us."}
354 =head2 function get_location()
356 Usage: my $location = $trial->get_location();
357 Desc:
358 Ret: [ location_id, 'location description' ]
359 Args:
360 Side Effects:
361 Example:
363 =cut
365 sub get_location {
366 my $self = shift;
368 if ($self->get_location_type_id()) {
369 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find( { project_id => $self->get_trial_id() , type_id=> $self->get_location_type_id() });
371 if ($row) {
372 my $loc = $self->bcs_schema->resultset('NaturalDiversity::NdGeolocation')->find( { nd_geolocation_id => $row->value() });
374 return [ $row->value(), $loc->description() ];
376 else {
377 return [];
382 =head2 function set_location()
384 Usage: $trial->set_location($location_id);
385 Desc:
386 Ret: nothing
387 Args:
388 Side Effects: database access
389 Example:
391 =cut
393 sub set_location {
394 my $self = shift;
395 my $location_id = shift;
396 my $project_id = $self->get_trial_id();
397 my $type_id = $self->get_location_type_id();
399 my $row = $self->bcs_schema()->resultset('Project::Projectprop')->find({
400 project_id => $project_id,
401 type_id => $type_id,
404 if ($row) {
405 $row->value($location_id);
406 $row->update();
408 else {
409 $row = $self->bcs_schema()->resultset('Project::Projectprop')->create({
410 project_id => $project_id,
411 type_id => $type_id,
412 value => $location_id,
417 =head2 function get_location_noaa_station_id()
419 Usage: my $noaa_station_id = $trial->get_location_noaa_station_id();
420 Desc:
421 Ret:
422 Args:
423 Side Effects:
424 Example:
426 =cut
428 sub get_location_noaa_station_id {
429 my $self = shift;
430 my $nd_geolocation_id = $self->bcs_schema->resultset('Project::Projectprop')->find( { project_id => $self->get_trial_id() , type_id=> $self->get_location_type_id() })->value();
431 my $noaa_station_id_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'noaa_station_id', 'geolocation_property')->cvterm_id();
433 my $q = "SELECT value FROM nd_geolocationprop WHERE nd_geolocation_id = ? AND type_id = ?;";
434 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
435 $h->execute($nd_geolocation_id, $noaa_station_id_cvterm_id);
436 my ($noaa_station_id) = $h->fetchrow_array();
437 return $noaa_station_id;
440 =head2 function get_breeding_programs()
442 Usage:
443 Desc: return associated breeding program info
444 Ret: returns a listref to [ id, name, desc ] listrefs
445 Args:
446 Side Effects:
447 Example:
449 =cut
451 sub get_breeding_programs {
452 my $self = shift;
454 my $breeding_program_cvterm_id = $self->get_breeding_program_cvterm_id();
456 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search( { 'subject_project_id' => $self->get_trial_id() } );
458 my $trial_row = $trial_rs -> first();
459 my $rs;
460 my @projects;
462 if ($trial_row) {
463 $rs = $self->bcs_schema->resultset('Project::Project')->search( { 'me.project_id' => $trial_row->object_project_id(), 'projectprops.type_id'=>$breeding_program_cvterm_id }, { join => 'projectprops' } );
465 while (my $row = $rs->next()) {
466 push @projects, [ $row->project_id, $row->name, $row->description ];
469 return \@projects;
472 =head2 function set_field_trials_source_field_trials()
474 Usage:
475 Desc: sets associated source field trials for the current field trial
476 Ret: returns an arrayref [ id, name ] of arrayrefs
477 Args: an arrayref [source_trial_id1, source_trial_id2]
478 Side Effects:
479 Example:
481 =cut
483 sub set_field_trials_source_field_trials {
484 my $self = shift;
485 my $source_field_trial_ids = shift;
486 my $schema = $self->bcs_schema;
487 my $field_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'field_trial_from_field_trial', 'project_relationship')->cvterm_id();
489 foreach (@$source_field_trial_ids){
490 if ($_){
491 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->create({
492 'subject_project_id' => $self->get_trial_id(),
493 'object_project_id' => $_,
494 'type_id' => $field_trial_from_field_trial_cvterm_id
498 my $projects = $self->get_field_trials_source_field_trials();
499 return $projects;
502 =head2 function get_field_trials_source_field_trials()
504 Usage:
505 Desc: return associated source field trials for the current field trial
506 Ret: returns an arrayref [ id, name ] of arrayrefs
507 Args:
508 Side Effects:
509 Example:
511 =cut
513 sub get_field_trials_source_field_trials {
514 my $self = shift;
515 my $schema = $self->bcs_schema;
516 my $field_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'field_trial_from_field_trial', 'project_relationship')->cvterm_id();
518 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search({
519 'me.subject_project_id' => $self->get_trial_id(),
520 'me.type_id' => $field_trial_from_field_trial_cvterm_id
521 }, {
522 join => 'object_project', '+select' => ['object_project.name'], '+as' => ['source_trial_name']
525 my @projects;
526 while (my $r = $trial_rs->next) {
527 push @projects, [ $r->object_project_id, $r->get_column('source_trial_name') ];
529 return \@projects;
532 =head2 function get_field_trials_sourced_from_field_trials()
534 Usage:
535 Desc: return associated source field trials for the current field trial
536 Ret: returns an arrayref [ id, name ] of arrayrefs
537 Args:
538 Side Effects:
539 Example:
541 =cut
543 sub get_field_trials_sourced_from_field_trials {
544 my $self = shift;
545 my $schema = $self->bcs_schema;
546 my $field_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'field_trial_from_field_trial', 'project_relationship')->cvterm_id();
548 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search({
549 'me.object_project_id' => $self->get_trial_id(),
550 'me.type_id' => $field_trial_from_field_trial_cvterm_id
551 }, {
552 join => 'subject_project', '+select' => ['subject_project.name'], '+as' => ['trial_name']
555 my @projects;
556 while (my $r = $trial_rs->next) {
557 push @projects, [ $r->subject_project_id, $r->get_column('trial_name') ];
559 return \@projects;
562 =head2 function set_genotyping_trials_from_field_trial()
564 Usage:
565 Desc: sets associated genotyping plates for the current field trial
566 Ret: returns an arrayref [ id, name ] of arrayrefs
567 Args: an arrayref [genotyping_trial_id1, genotyping_trial_id2]
568 Side Effects:
569 Example:
571 =cut
573 sub set_genotyping_trials_from_field_trial {
574 my $self = shift;
575 my $source_field_trial_ids = shift;
576 my $schema = $self->bcs_schema;
577 my $genotyping_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'genotyping_trial_from_field_trial', 'project_relationship')->cvterm_id();
579 foreach (@$source_field_trial_ids){
580 if ($_){
581 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->create({
582 'subject_project_id' => $self->get_trial_id(),
583 'object_project_id' => $_,
584 'type_id' => $genotyping_trial_from_field_trial_cvterm_id
588 my $projects = $self->get_genotyping_trials_from_field_trial();
589 return $projects;
592 =head2 function get_genotyping_trials_from_field_trial()
594 Usage:
595 Desc: return associated genotyping plates for the current field trial
596 Ret: returns an arrayref [ id, name ] of arrayrefs
597 Args:
598 Side Effects:
599 Example:
601 =cut
603 sub get_genotyping_trials_from_field_trial {
604 my $self = shift;
605 my $schema = $self->bcs_schema;
606 my $genotyping_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'genotyping_trial_from_field_trial', 'project_relationship')->cvterm_id();
608 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search({
609 'me.subject_project_id' => $self->get_trial_id(),
610 'me.type_id' => $genotyping_trial_from_field_trial_cvterm_id
611 }, {
612 join => 'object_project', '+select' => ['object_project.name'], '+as' => ['source_trial_name']
615 my @projects;
616 while (my $r = $trial_rs->next) {
617 push @projects, [ $r->object_project_id, $r->get_column('source_trial_name') ];
619 return \@projects;
622 =head2 function set_source_field_trials_for_genotyping_trial()
624 Usage:
625 Desc: sets associated field trials for the current genotyping plate
626 Ret: returns an arrayref [ id, name ] of arrayrefs
627 Args: an arrayref [field_trial_id1, field_trial_id2]
628 Side Effects:
629 Example:
631 =cut
633 sub set_source_field_trials_for_genotyping_trial {
634 my $self = shift;
635 my $source_field_trial_ids = shift;
636 my $schema = $self->bcs_schema;
637 my $genotyping_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'genotyping_trial_from_field_trial', 'project_relationship')->cvterm_id();
639 foreach (@$source_field_trial_ids){
640 if ($_){
641 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->create({
642 'object_project_id' => $self->get_trial_id(),
643 'subject_project_id' => $_,
644 'type_id' => $genotyping_trial_from_field_trial_cvterm_id
648 my $projects = $self->get_field_trials_source_of_genotyping_trial();
649 return $projects;
652 =head2 function get_field_trials_source_of_genotyping_trial()
654 Usage:
655 Desc: return associated field trials for current genotying trial
656 Ret: returns an arrayref [ id, name ] of arrayrefs
657 Args:
658 Side Effects:
659 Example:
661 =cut
663 sub get_field_trials_source_of_genotyping_trial {
664 my $self = shift;
665 my $schema = $self->bcs_schema;
666 my $genotyping_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'genotyping_trial_from_field_trial', 'project_relationship')->cvterm_id();
668 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search({
669 'me.object_project_id' => $self->get_trial_id(),
670 'me.type_id' => $genotyping_trial_from_field_trial_cvterm_id
671 }, {
672 join => 'subject_project', '+select' => ['subject_project.name'], '+as' => ['source_trial_name']
675 my @projects;
676 while (my $r = $trial_rs->next) {
677 push @projects, [ $r->subject_project_id, $r->get_column('source_trial_name') ];
679 return \@projects;
683 =head2 function set_crossing_trials_from_field_trial()
685 Usage:
686 Desc: sets associated crossing trials for the current field trial
687 Ret: returns an arrayref [ id, name ] of arrayrefs
688 Args: an arrayref [crossing_trial_id1, crossing_trial_id2]
689 Side Effects:
690 Example:
692 =cut
694 sub set_crossing_trials_from_field_trial {
695 my $self = shift;
696 my $source_field_trial_ids = shift;
697 my $schema = $self->bcs_schema;
698 my $genotyping_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'crossing_trial_from_field_trial', 'project_relationship')->cvterm_id();
700 foreach (@$source_field_trial_ids){
701 if ($_){
702 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->create({
703 'subject_project_id' => $self->get_trial_id(),
704 'object_project_id' => $_,
705 'type_id' => $genotyping_trial_from_field_trial_cvterm_id
709 my $projects = $self->get_crossing_trials_from_field_trial();
710 return $projects;
713 =head2 function get_crossing_trials_from_field_trial()
715 Usage:
716 Desc: return associated crossing trials for athe current field trial
717 Ret: returns an arrayref [ id, name ] of arrayrefs
718 Args:
719 Side Effects:
720 Example:
722 =cut
724 sub get_crossing_trials_from_field_trial {
725 my $self = shift;
726 my $schema = $self->bcs_schema;
727 my $crossing_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'crossing_trial_from_field_trial', 'project_relationship')->cvterm_id();
729 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search({
730 'me.subject_project_id' => $self->get_trial_id(),
731 'me.type_id' => $crossing_trial_from_field_trial_cvterm_id
732 }, {
733 join => 'object_project', '+select' => ['object_project.name'], '+as' => ['source_trial_name']
736 my @projects;
737 while (my $r = $trial_rs->next) {
738 push @projects, [ $r->object_project_id, $r->get_column('source_trial_name') ];
740 return \@projects;
743 =head2 function get_field_trials_source_of_crossing_trial()
745 Usage:
746 Desc: return associated field trials for the current crossing trial
747 Ret: returns an arrayref [ id, name ] of arrayrefs
748 Args:
749 Side Effects:
750 Example:
752 =cut
754 sub get_field_trials_source_of_crossing_trial {
755 my $self = shift;
756 my $schema = $self->bcs_schema;
757 my $crossing_trial_from_field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'crossing_trial_from_field_trial', 'project_relationship')->cvterm_id();
759 my $trial_rs= $self->bcs_schema->resultset('Project::ProjectRelationship')->search({
760 'me.object_project_id' => $self->get_trial_id(),
761 'me.type_id' => $crossing_trial_from_field_trial_cvterm_id
762 }, {
763 join => 'subject_project', '+select' => ['subject_project.name'], '+as' => ['source_trial_name']
766 my @projects;
767 while (my $r = $trial_rs->next) {
768 push @projects, [ $r->subject_project_id, $r->get_column('source_trial_name') ];
770 return \@projects;
774 =head2 function get_project_type()
776 Usage: [ $project_type_cvterm_id, $project_type_name ] = $t -> get_project_type();
777 Desc:
778 Ret:
779 Args:
780 Side Effects:
781 Example:
783 =cut
785 sub get_project_type {
786 my $self = shift;
788 my @project_type_ids = CXGN::Trial::get_all_project_types($self->bcs_schema());
790 my @ids = map { $_->[0] } @project_type_ids;
791 my $rs = $self->bcs_schema()->resultset('Project::Projectprop')->search(
793 type_id => { -in => [ @ids ] },
794 project_id => $self->get_trial_id()
797 if ($rs->count() > 0) {
798 my $type_id = $rs->first()->type_id();
799 foreach my $pt (@project_type_ids) {
800 if ($type_id == $pt->[0]) {
801 #print STDERR "[get_project_type] ".$pt->[0]." ".$pt->[1]."\n";
802 return $pt;
806 return undef;
811 =head2 function set_project_type()
813 Usage: $t -> set_project_type($type);
814 Desc:
815 Ret:
816 Args:
817 Side Effects:
818 Example:
820 =cut
822 sub set_project_type {
823 my $self = shift;
824 my $type_id = shift;
825 my $project_id = $self->get_trial_id();
826 my @project_type_ids = CXGN::Trial::get_all_project_types($self->bcs_schema());
827 my $type;
829 foreach my $pt (@project_type_ids) {
830 if ($pt->[0] eq $type_id) {
831 $type = $pt->[1];
835 my @ids = map { $_->[0] } @project_type_ids;
836 my $rs = $self->bcs_schema()->resultset('Project::Projectprop')->search({
837 type_id => { -in => [ @ids ] },
838 project_id => $project_id
840 if (my $row = $rs->next()) {
841 $row->delete();
844 my $row = $self->bcs_schema()->resultset('Project::Projectprop')->create({
845 project_id => $project_id,
846 type_id => $type_id,
847 value => $type,
852 sub set_design_type {
853 my $self = shift;
854 my $design_type = shift;
856 my $design_cv_type = $self->bcs_schema->resultset('Cv::Cvterm')->find( { name => 'design' });
857 if (!$design_cv_type) {
858 print STDERR "Design CV term not found. Cannot set design type.\n";
859 return;
861 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create(
863 project_id => $self->get_trial_id(),
864 type_id => $design_cv_type->cvterm_id(),
866 $row->value($design_type);
867 $row->update();
870 =head2 accessors get_breeding_program(), set_breeding_program()
872 Usage:
873 Desc:
874 Ret:
875 Args:
876 Side Effects:
877 Example:
879 =cut
881 sub get_breeding_program {
883 my $self = shift;
885 my $rs = $self->bcs_schema()->resultset("Project::ProjectRelationship")->search({
886 subject_project_id => $self->get_trial_id(),
887 type_id => $self->get_breeding_program_trial_relationship_cvterm_id(),
889 if ($rs->count() == 0) {
890 return undef;
893 my $bp_rs = $self->bcs_schema()->resultset("Project::Project")->search({
894 project_id => $rs->first()->object_project_id()
896 if ($bp_rs->count > 0) {
897 return $bp_rs->first()->name();
900 return undef;
903 sub set_breeding_program {
904 my $self = shift;
905 my $breeding_program_id = shift;
906 my $trial_id = $self->get_trial_id();
907 my $type_id = $self->get_breeding_program_trial_relationship_cvterm_id();
909 eval {
910 my $row = $self->bcs_schema->resultset("Project::ProjectRelationship")->find ({
911 subject_project_id => $trial_id,
912 type_id => $type_id,
915 if ($row) {
916 $row->object_project_id($breeding_program_id);
917 $row->update();
919 else {
920 $row = $self->bcs_schema->resultset("Project::ProjectRelationship")->create ({
921 object_project_id => $breeding_program_id,
922 subject_project_id => $trial_id,
923 type_id => $type_id,
925 $row->insert();
929 if ($@) {
930 print STDERR "ERROR: $@\n";
931 return { error => "An error occurred while setting the trial's breeding program." };
933 return {};
937 =head2 accessors get_name(), set_name()
939 Usage:
940 Desc: retrieve and store project name from/to database
941 Ret:
942 Args:
943 Side Effects: setter modifies the database
944 Example:
946 =cut
948 sub get_name {
949 my $self = shift;
950 my $row = $self->bcs_schema->resultset('Project::Project')->find( { project_id => $self->get_trial_id() });
952 if ($row) {
953 return $row->name();
957 sub set_name {
958 my $self = shift;
959 my $name = shift;
960 my $row = $self->bcs_schema->resultset('Project::Project')->find( { project_id => $self->get_trial_id() });
961 if ($row) {
962 $row->name($name);
963 $row->update();
967 =head2 accessors get_project_start_date(), set_project_start_date()
969 Usage: $t->set_project_start_date("2016/09/17");
970 Desc: sets the projects project_start_date property.
971 The date format in the setter has to be
972 YYYY/MM/DD
973 Ret:
974 Args:
975 Side Effects:
976 Example:
978 =cut
980 sub get_project_start_date {
981 my $self = shift;
983 my $project_start_date_cvterm_id = $self->get_project_start_date_cvterm_id();
984 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find({
985 project_id => $self->get_trial_id(),
986 type_id => $project_start_date_cvterm_id,
989 my $calendar_funcs = CXGN::Calendar->new({});
990 return $row ? $calendar_funcs->display_start_date($row->value()) : undef;
993 sub set_project_start_date {
994 my $self = shift;
995 my $project_start_date = shift;
997 my $calendar_funcs = CXGN::Calendar->new({});
998 if (my $project_start_date_event = $calendar_funcs->check_value_format($project_start_date) ) {
999 my $project_start_date_cvterm_id = $self->get_project_start_date_cvterm_id();
1000 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1001 project_id => $self->get_trial_id(),
1002 type_id => $project_start_date_cvterm_id,
1005 $row->value($project_start_date_event);
1006 $row->update();
1007 } else {
1008 print STDERR "date format did not pass check while preparing to set project start date: $project_start_date \n";
1012 =head2 accessors get_harvest_date(), set_harvest_date()
1014 Usage: $t->set_harvest_date("2016/09/17");
1015 Desc: sets the projects harvest_date property.
1016 The date format in the setter has to be
1017 YYYY/MM/DD
1018 Ret:
1019 Args:
1020 Side Effects:
1021 Example:
1023 =cut
1025 sub get_harvest_date {
1026 my $self = shift;
1028 my $harvest_date_cvterm_id = $self->get_harvest_date_cvterm_id();
1029 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find(
1031 project_id => $self->get_trial_id(),
1032 type_id => $harvest_date_cvterm_id,
1035 my $calendar_funcs = CXGN::Calendar->new({});
1037 if ($row) {
1038 my $harvest_date = $calendar_funcs->display_start_date($row->value());
1039 return $harvest_date;
1040 } else {
1041 return;
1045 sub set_harvest_date {
1046 my $self = shift;
1047 my $harvest_date = shift;
1049 my $calendar_funcs = CXGN::Calendar->new({});
1051 if (my $harvest_event = $calendar_funcs->check_value_format($harvest_date) ) {
1053 my $harvest_date_cvterm_id = $self->get_harvest_date_cvterm_id();
1055 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create(
1057 project_id => $self->get_trial_id(),
1058 type_id => $harvest_date_cvterm_id,
1061 $row->value($harvest_event);
1062 $row->update();
1063 } else {
1064 print STDERR "date format did not pass check while preparing to set harvest date: $harvest_date \n";
1068 sub remove_harvest_date {
1069 my $self = shift;
1070 my $harvest_date = shift;
1072 my $calendar_funcs = CXGN::Calendar->new({});
1073 if (my $harvest_event = $calendar_funcs->check_value_format($harvest_date) ) {
1075 my $harvest_date_cvterm_id = $self->get_harvest_date_cvterm_id();
1077 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create(
1079 project_id => $self->get_trial_id(),
1080 type_id => $harvest_date_cvterm_id,
1081 value => $harvest_event,
1084 if ($row) {
1085 print STDERR "Removing harvest date $harvest_event from trial ".$self->get_trial_id()."\n";
1086 $row->delete();
1088 } else {
1089 print STDERR "date format did not pass check while preparing to delete harvest date: $harvest_date \n";
1094 =head2 accessors get_planting_date(), set_planting_date()
1096 Usage:
1097 Desc:
1098 Ret:
1099 Args:
1100 Side Effects:
1101 Example:
1103 =cut
1105 sub get_planting_date {
1106 my $self = shift;
1108 my $planting_date_cvterm_id = $self->get_planting_date_cvterm_id();
1109 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find(
1111 project_id => $self->get_trial_id(),
1112 type_id => $planting_date_cvterm_id,
1115 my $calendar_funcs = CXGN::Calendar->new({});
1117 if ($row) {
1118 my $harvest_date = $calendar_funcs->display_start_date($row->value());
1119 return $harvest_date;
1120 } else {
1121 return;
1125 sub set_planting_date {
1126 my $self = shift;
1127 my $planting_date = shift;
1129 my $calendar_funcs = CXGN::Calendar->new({});
1131 if (my $planting_event = $calendar_funcs->check_value_format($planting_date) ) {
1133 my $planting_date_cvterm_id = $self->get_planting_date_cvterm_id();
1135 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create(
1137 project_id => $self->get_trial_id(),
1138 type_id => $planting_date_cvterm_id,
1141 $row->value($planting_event);
1142 $row->update();
1143 } else {
1144 print STDERR "date format did not pass check while preparing to set planting date: $planting_date \n";
1148 sub remove_planting_date {
1149 my $self = shift;
1150 my $planting_date = shift;
1152 my $calendar_funcs = CXGN::Calendar->new({});
1153 if (my $planting_event = $calendar_funcs->check_value_format($planting_date) ) {
1155 my $planting_date_cvterm_id = $self->get_planting_date_cvterm_id();
1157 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create(
1159 project_id => $self->get_trial_id(),
1160 type_id => $planting_date_cvterm_id,
1161 value => $planting_event,
1164 if ($row) {
1165 print STDERR "Removing planting date $planting_event from trial ".$self->get_trial_id()."\n";
1166 $row->delete();
1168 } else {
1169 print STDERR "date format did not pass check while preparing to delete planting date: $planting_date \n";
1174 =head2 accessors get_temperature_averaged_gdd(), set_temperature_averaged_gdd()
1176 Usage:
1177 Desc:
1178 Ret:
1179 Args:
1180 Side Effects:
1181 Example:
1183 =cut
1185 sub get_temperature_averaged_gdd {
1186 my $self = shift;
1188 my $temperature_averaged_gdd_cvterm_id = $self->get_temperature_averaged_gdd_cvterm_id();
1189 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find({
1190 project_id => $self->get_trial_id(),
1191 type_id => $temperature_averaged_gdd_cvterm_id,
1194 if ($row) {
1195 return $row->value;
1196 } else {
1197 return;
1201 sub set_temperature_averaged_gdd {
1202 my $self = shift;
1203 my $temperature_averaged_gdd = shift;
1205 my $temperature_averaged_gdd_cvterm_id = $self->get_temperature_averaged_gdd_cvterm_id();
1206 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1207 project_id => $self->get_trial_id(),
1208 type_id => $temperature_averaged_gdd_cvterm_id,
1210 $row->value($temperature_averaged_gdd);
1211 $row->update();
1214 sub remove_temperature_averaged_gdd {
1215 my $self = shift;
1216 my $temperature_averaged_gdd = shift;
1218 my $temperature_averaged_gdd_cvterm_id = $self->get_temperature_averaged_gdd_cvterm_id();
1219 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1220 project_id => $self->get_trial_id(),
1221 type_id => $temperature_averaged_gdd_cvterm_id,
1222 value => $temperature_averaged_gdd,
1224 if ($row) {
1225 print STDERR "Removing $temperature_averaged_gdd from trial ".$self->get_trial_id()."\n";
1226 $row->delete();
1230 sub get_temperature_averaged_gdd_cvterm_id {
1231 my $self = shift;
1232 return SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'drone_run_averaged_temperature_growing_degree_days', 'project_property')->cvterm_id();
1235 =head2 accessors get_related_time_cvterms_json(), set_related_time_cvterms_json()
1237 Usage:
1238 Desc:
1239 Ret:
1240 Args:
1241 Side Effects:
1242 Example:
1244 =cut
1246 sub get_related_time_cvterms_json {
1247 my $self = shift;
1249 my $cvterm_id = $self->get_related_time_cvterms_json_cvterm_id();
1250 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find({
1251 project_id => $self->get_trial_id(),
1252 type_id => $cvterm_id,
1255 if ($row) {
1256 return $row->value;
1257 } else {
1258 return;
1262 sub set_related_time_cvterms_json {
1263 my $self = shift;
1264 my $related_time_terms_json = shift;
1266 my $cvterm_id = $self->get_related_time_cvterms_json_cvterm_id();
1267 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1268 project_id => $self->get_trial_id(),
1269 type_id => $cvterm_id,
1271 $row->value($related_time_terms_json);
1272 $row->update();
1275 sub remove_related_time_cvterms_json {
1276 my $self = shift;
1277 my $related_time_terms_json = shift;
1279 my $cvterm_id = $self->get_related_time_cvterms_json_cvterm_id();
1280 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1281 project_id => $self->get_trial_id(),
1282 type_id => $cvterm_id,
1283 value => $related_time_terms_json,
1285 if ($row) {
1286 print STDERR "Removing $related_time_terms_json from trial ".$self->get_trial_id()."\n";
1287 $row->delete();
1291 sub get_related_time_cvterms_json_cvterm_id {
1292 my $self = shift;
1293 return SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'drone_run_related_time_cvterms_json', 'project_property')->cvterm_id();
1296 =head2 function get_management_factor_date()
1298 Usage: $trial->get_management_factor_date();
1299 Desc: Field management factors are a project and are therefore instantiated with CXGN::Trial. this gets the date projectprop
1300 Ret: Returns string
1301 Args:
1302 Side Effects:
1303 Example:
1305 =cut
1307 sub get_management_factor_date {
1308 my $self = shift;
1310 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find({
1311 project_id => $self->get_trial_id(),
1312 type_id => $self->get_mangement_factor_date_cvterm_id()
1314 my $calendar_funcs = CXGN::Calendar->new({});
1316 if ($row) {
1317 return $calendar_funcs->display_start_date($row->value());
1318 } else {
1319 return;
1323 sub set_management_factor_date {
1324 my $self = shift;
1325 my $management_factor_date = shift;
1327 my $calendar_funcs = CXGN::Calendar->new({});
1329 if (my $management_factor_event = $calendar_funcs->check_value_format($management_factor_date) ) {
1330 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1331 project_id => $self->get_trial_id(),
1332 type_id => $self->get_mangement_factor_date_cvterm_id()
1335 $row->value($management_factor_event);
1336 $row->update();
1337 } else {
1338 print STDERR "date format did not pass check while preparing to set management factor date: $management_factor_date \n";
1342 sub get_mangement_factor_date_cvterm_id {
1343 my $self = shift;
1344 return SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'management_factor_date', 'project_property')->cvterm_id();
1347 sub get_mangement_factor_type_cvterm_id {
1348 my $self = shift;
1349 return SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'management_factor_type', 'project_property')->cvterm_id();
1352 sub get_management_factor_type {
1353 my $self = shift;
1355 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find({
1356 project_id => $self->get_trial_id(),
1357 type_id => $self->get_mangement_factor_type_cvterm_id()
1360 if ($row) {
1361 return $row->value();
1362 } else {
1363 return;
1367 =head2 accessors get_phenotypes_fully_uploaded(), set_phenotypes_fully_uploaded()
1369 Usage: When a trial's phenotypes have been fully upload, the user can set a projectprop called 'phenotypes_fully_uploaded' with a value of 1
1370 Desc:
1371 Ret:
1372 Args:
1373 Side Effects:
1374 Example:
1376 =cut
1378 sub get_phenotypes_fully_uploaded {
1379 my $self = shift;
1380 return $self->_get_projectprop('phenotypes_fully_uploaded');
1383 sub set_phenotypes_fully_uploaded {
1384 my $self = shift;
1385 my $value = shift;
1386 $self->_set_projectprop('phenotypes_fully_uploaded', $value);
1389 =head2 accessors get_raw_data_link(), set_raw_data_link()
1391 Usage: For genotyping plates, a genotyping facility can be set as a projectprop value e.g. 'igd'
1392 Desc:
1393 Ret:
1394 Args:
1395 Side Effects:
1396 Example:
1398 =cut
1400 sub get_raw_data_link {
1401 my $self = shift;
1402 return $self->_get_projectprop('raw_data_link');
1405 sub set_raw_data_link {
1406 my $self = shift;
1407 my $value = shift;
1408 $self->_set_projectprop('raw_data_link', $value);
1412 =head2 accessors get_genotyping_facility(), set_genotyping_facility()
1414 Usage: For genotyping plates, a genotyping facility can be set as a projectprop value e.g. 'igd'
1415 Desc:
1416 Ret:
1417 Args:
1418 Side Effects:
1419 Example:
1421 =cut
1423 sub get_genotyping_facility {
1424 my $self = shift;
1425 return $self->_get_projectprop('genotyping_facility');
1428 sub set_genotyping_facility {
1429 my $self = shift;
1430 my $value = shift;
1431 $self->_set_projectprop('genotyping_facility', $value);
1434 =head2 accessors get_genotyping_facility_submitted(), set_genotyping_facility_submitted()
1436 Usage: For genotyping plates, if a genotyping plate has been submitted to genotyping facility and the plate is stored in out system, this stockprop can be set to 'yes'
1437 Desc:
1438 Ret:
1439 Args:
1440 Side Effects:
1441 Example:
1443 =cut
1445 sub get_genotyping_facility_submitted {
1446 my $self = shift;
1447 return $self->_get_projectprop('genotyping_facility_submitted');
1450 sub set_genotyping_facility_submitted {
1451 my $self = shift;
1452 my $value = shift;
1453 $self->_set_projectprop('genotyping_facility_submitted', $value);
1456 =head2 accessors get_genotyping_facility_status(), set_genotyping_facility_status()
1458 Usage: For genotyping plates, if a genotyping plate has been submitted to genotyping facility, the status of that plate can be set here
1459 Desc:
1460 Ret:
1461 Args:
1462 Side Effects:
1463 Example:
1465 =cut
1467 sub get_genotyping_facility_status {
1468 my $self = shift;
1469 return $self->_get_projectprop('genotyping_facility_status');
1472 sub set_genotyping_facility_status {
1473 my $self = shift;
1474 my $value = shift;
1475 $self->_set_projectprop('genotyping_facility_status', $value);
1478 =head2 accessors get_genotyping_plate_format(), set_genotyping_plate_format()
1480 Usage: For genotyping plates, this records if it is 96 wells or 384 or other
1481 Desc:
1482 Ret:
1483 Args:
1484 Side Effects:
1485 Example:
1487 =cut
1489 sub get_genotyping_plate_format {
1490 my $self = shift;
1491 return $self->_get_projectprop('genotyping_plate_format');
1494 sub set_genotyping_plate_format {
1495 my $self = shift;
1496 my $value = shift;
1497 $self->_set_projectprop('genotyping_plate_format', $value);
1500 =head2 accessors get_genotyping_plate_sample_type(), set_genotyping_plate_sample_type()
1502 Usage: For genotyping plates, this records sample type of plate e.g. DNA
1503 Desc:
1504 Ret:
1505 Args:
1506 Side Effects:
1507 Example:
1509 =cut
1511 sub get_genotyping_plate_sample_type {
1512 my $self = shift;
1513 return $self->_get_projectprop('genotyping_plate_sample_type');
1516 sub set_genotyping_plate_sample_type {
1517 my $self = shift;
1518 my $value = shift;
1519 $self->_set_projectprop('genotyping_plate_sample_type', $value);
1522 =head2 accessors get_field_trial_is_planned_to_be_genotyped(), set_field_trial_is_planned_to_be_genotyped()
1524 Usage: For field trials, this records whether the trial will be genotyped
1525 Desc:
1526 Ret:
1527 Args:
1528 Side Effects:
1529 Example:
1531 =cut
1533 sub get_field_trial_is_planned_to_be_genotyped {
1534 my $self = shift;
1535 return $self->_get_projectprop('field_trial_is_planned_to_be_genotyped');
1538 sub set_field_trial_is_planned_to_be_genotyped {
1539 my $self = shift;
1540 my $value = shift;
1541 $self->_set_projectprop('field_trial_is_planned_to_be_genotyped', $value);
1544 =head2 accessors get_field_trial_is_planned_to_cross(), set_field_trial_is_planned_to_cross()
1546 Usage: For field trials, this records whether the trial will be involved in crosses
1547 Desc:
1548 Ret:
1549 Args:
1550 Side Effects:
1551 Example:
1553 =cut
1555 sub get_field_trial_is_planned_to_cross {
1556 my $self = shift;
1557 return $self->_get_projectprop('field_trial_is_planned_to_cross');
1560 sub set_field_trial_is_planned_to_cross {
1561 my $self = shift;
1562 my $value = shift;
1563 $self->_set_projectprop('field_trial_is_planned_to_cross', $value);
1566 =head2 accessors get_plot_width(), set_plot_width()
1568 Usage: For field trials, this records plot width in meters
1569 Desc:
1570 Ret:
1571 Args:
1572 Side Effects:
1573 Example:
1575 =cut
1577 sub get_plot_width {
1578 my $self = shift;
1579 return $self->_get_projectprop('plot_width');
1582 sub set_plot_width {
1583 my $self = shift;
1584 my $value = shift;
1585 $self->_set_projectprop('plot_width', $value);
1588 =head2 accessors get_plot_length(), set_plot_length()
1590 Usage: For field trials, this records plot length in meters
1591 Desc:
1592 Ret:
1593 Args:
1594 Side Effects:
1595 Example:
1597 =cut
1599 sub get_plot_length {
1600 my $self = shift;
1601 return $self->_get_projectprop('plot_length');
1604 sub set_plot_length {
1605 my $self = shift;
1606 my $value = shift;
1607 $self->_set_projectprop('plot_length', $value);
1610 =head2 accessors get_field_size(), set_field_size()
1612 Usage: For field trials, this recordsfield size in hectares
1613 Desc:
1614 Ret:
1615 Args:
1616 Side Effects:
1617 Example:
1619 =cut
1621 sub get_field_size {
1622 my $self = shift;
1623 return $self->_get_projectprop('field_size');
1626 sub set_field_size {
1627 my $self = shift;
1628 my $value = shift;
1629 $self->_set_projectprop('field_size', $value);
1633 sub _get_projectprop {
1634 my $self = shift;
1635 my $term = shift;
1636 my $cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, $term, 'project_property')->cvterm_id;
1637 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find({
1638 project_id => $self->get_trial_id(),
1639 type_id => $cvterm_id,
1642 if ($row) {
1643 return $row->value;
1644 } else {
1645 return;
1649 sub _set_projectprop {
1650 my $self = shift;
1651 my $term = shift;
1652 my $value = shift;
1653 my $cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, $term, 'project_property')->cvterm_id;
1654 my $row = $self->bcs_schema->resultset('Project::Projectprop')->find_or_create({
1655 project_id => $self->get_trial_id(),
1656 type_id => $cvterm_id,
1658 $row->value($value);
1659 $row->update();
1662 =head2 function delete_phenotype_data()
1664 Usage:
1665 Desc:
1666 Ret:
1667 Args:
1668 Side Effects:
1669 Example:
1671 =cut
1673 # note: you may need to delete the metadata before deleting the phenotype data (see function).
1674 # this function has a test!
1676 sub delete_phenotype_data {
1677 my $self = shift;
1678 my $basepath = shift;
1679 my $dbhost = shift;
1680 my $dbname = shift;
1681 my $dbuser = shift;
1682 my $dbpass = shift;
1683 my $temp_file_nd_experiment_id = shift;
1685 my $trial_id = $self->get_trial_id();
1686 my $nd_experiment_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'phenotyping_experiment', 'experiment_type')->cvterm_id();
1688 my $q_search = "
1689 SELECT phenotype_id, nd_experiment_id, file_id
1690 FROM phenotype
1691 JOIN nd_experiment_phenotype using(phenotype_id)
1692 JOIN nd_experiment using(nd_experiment_id)
1693 JOIN nd_experiment_stock using(nd_experiment_id)
1694 JOIN nd_experiment_project using(nd_experiment_id)
1695 LEFT JOIN phenome.nd_experiment_md_files using(nd_experiment_id)
1696 JOIN stock using(stock_id)
1697 WHERE project_id = $trial_id
1698 AND nd_experiment.type_id = $nd_experiment_type_id;
1700 my $h = $self->bcs_schema->storage->dbh()->prepare($q_search);
1701 $h->execute();
1703 my %phenotype_ids_and_nd_experiment_ids_to_delete;
1704 while (my ($phenotype_id, $nd_experiment_id, $file_id) = $h->fetchrow_array()) {
1705 push @{$phenotype_ids_and_nd_experiment_ids_to_delete{phenotype_ids}}, $phenotype_id;
1706 push @{$phenotype_ids_and_nd_experiment_ids_to_delete{nd_experiment_ids}}, $nd_experiment_id;
1708 return delete_phenotype_values_and_nd_experiment_md_values($dbhost, $dbname, $dbuser, $dbpass, $temp_file_nd_experiment_id, $basepath, $self->bcs_schema, \%phenotype_ids_and_nd_experiment_ids_to_delete);
1711 #Class function
1712 sub delete_phenotype_values_and_nd_experiment_md_values {
1713 my $dbhost = shift;
1714 my $dbname = shift;
1715 my $dbuser = shift;
1716 my $dbpass = shift;
1717 my $temp_file_nd_experiment_id = shift;
1718 my $basepath = shift;
1719 my $schema = shift;
1720 my $phenotype_ids_and_nd_experiment_ids_to_delete = shift;
1722 my $coderef = sub {
1723 my $phenotype_id_sql = join (",", @{$phenotype_ids_and_nd_experiment_ids_to_delete->{phenotype_ids}});
1724 my $q_pheno_delete = "DELETE FROM phenotype WHERE phenotype_id IN ($phenotype_id_sql);";
1725 my $h2 = $schema->storage->dbh()->prepare($q_pheno_delete);
1726 $h2->execute();
1727 my $nd_experiment_id_sql = join (",", @{$phenotype_ids_and_nd_experiment_ids_to_delete->{nd_experiment_ids}});
1728 my $q_nd_exp_files_delete = "DELETE FROM phenome.nd_experiment_md_files WHERE nd_experiment_id IN ($nd_experiment_id_sql);";
1729 my $h3 = $schema->storage->dbh()->prepare($q_nd_exp_files_delete);
1730 $h3->execute();
1731 my $q_nd_exp_files_images_delete = "DELETE FROM phenome.nd_experiment_md_images WHERE nd_experiment_id IN ($nd_experiment_id_sql);";
1732 my $h4 = $schema->storage->dbh()->prepare($q_nd_exp_files_images_delete);
1733 $h4->execute();
1735 open (my $fh, ">", $temp_file_nd_experiment_id ) || die ("\nERROR: the file $temp_file_nd_experiment_id could not be found\n" );
1736 foreach (@{$phenotype_ids_and_nd_experiment_ids_to_delete->{nd_experiment_ids}}) {
1737 print $fh "$_\n";
1739 close($fh);
1741 my $async_delete = CXGN::Tools::Run->new();
1742 $async_delete->run_async("perl $basepath/bin/delete_nd_experiment_entries.pl -H $dbhost -D $dbname -U $dbuser -P $dbpass -i $temp_file_nd_experiment_id");
1744 print STDERR "DELETED ".scalar(@{$phenotype_ids_and_nd_experiment_ids_to_delete->{phenotype_ids}})." Phenotype Values and nd_experiment_md_file_links (nd_experiment entries may still be in deletion in asynchronous process.)\n";
1747 my $error;
1748 try {
1749 $schema->txn_do($coderef);
1750 } catch {
1751 print STDERR "ERROR: $_\n";
1752 $error = $_;
1754 return $error;
1757 =head2 function delete_field_layout()
1759 Usage:
1760 Desc:
1761 Ret:
1762 Args:
1763 Side Effects:
1764 Example:
1766 =cut
1769 # this function has a test!
1771 sub delete_field_layout {
1772 my $self = shift;
1774 my $trial_id = $self->get_trial_id();
1776 if (scalar(@{$self->get_genotyping_trials_from_field_trial}) > 0) {
1777 return 'This field trial has been linked to genotyping trials already, and cannot be easily deleted.';
1779 if (scalar(@{$self->get_field_trials_source_of_genotyping_trial}) > 0) {
1780 return 'This genotyping trial has been linked to field trials already, and cannot be easily deleted.';
1782 if (scalar(@{$self->get_crossing_trials_from_field_trial}) >0) {
1783 return 'This field trial has been linked to crossing trials already, and cannot be easily deleted.';
1785 if (scalar(@{$self->get_field_trials_source_of_crossing_trial}) >0) {
1786 return 'This crossing trial has been linked to field trials already, and cannot be easily deleted.';
1789 # Note: metadata entries need to be deleted separately using delete_metadata()
1791 my $error = '';
1792 eval {
1793 $self->bcs_schema()->txn_do(
1794 sub {
1795 #print STDERR "DELETING FIELD LAYOUT FOR TRIAL $trial_id...\n";
1796 $self->_delete_field_layout_experiment();
1797 #print STDERR "DELETE MANAGEMENT FACTORS FOR TRIAL $trial_id...\n";
1798 $self->_delete_management_factors_experiments();
1802 if ($@) {
1803 print STDERR "ERROR $@\n";
1804 return "An error occurred: $@\n";
1807 return '';
1810 =head2 function get_phenotype_metadata()
1812 Usage: $trial->get_phenotype_metadata();
1813 Desc: retrieves metadata.md_file entries for this trial. These entries are created during StorePhenotypes
1814 Ret:
1815 Args:
1816 Side Effects:
1817 Example:
1819 =cut
1821 sub get_phenotype_metadata {
1822 my $self = shift;
1823 my $trial_id = $self->get_trial_id();
1824 my @file_array;
1825 my %file_info;
1826 my $q = "SELECT file_id, m.create_date, p.sp_person_id, p.username, basename, dirname, filetype FROM nd_experiment_project JOIN nd_experiment_phenotype USING(nd_experiment_id) JOIN phenome.nd_experiment_md_files ON (nd_experiment_phenotype.nd_experiment_id=nd_experiment_md_files.nd_experiment_id) LEFT JOIN metadata.md_files using(file_id) LEFT JOIN metadata.md_metadata as m using(metadata_id) LEFT JOIN sgn_people.sp_person as p ON (p.sp_person_id=m.create_person_id) WHERE project_id=? and m.obsolete = 0 and NOT (metadata.md_files.filetype='generated from plot from plant phenotypes') and NOT (metadata.md_files.filetype='direct phenotyping') ORDER BY file_id ASC";
1827 my $h = $self->bcs_schema->storage()->dbh()->prepare($q);
1828 $h->execute($trial_id);
1830 while (my ($file_id, $create_date, $person_id, $username, $basename, $dirname, $filetype) = $h->fetchrow_array()) {
1831 $file_info{$file_id} = [$file_id, $create_date, $person_id, $username, $basename, $dirname, $filetype];
1833 foreach (keys %file_info){
1834 push @file_array, $file_info{$_};
1836 return \@file_array;
1839 =head2 function delete_phenotype_metadata()
1841 Usage: $trial->delete_phenotype_metadata($metadata_schema, $phenome_schema);
1842 Desc: obsoletes the metadata entries for this trial.
1843 Ret:
1844 Args:
1845 Side Effects:
1846 Example:
1848 =cut
1850 sub delete_phenotype_metadata {
1851 my $self = shift;
1852 my $metadata_schema = shift;
1853 my $phenome_schema = shift;
1855 if (!$metadata_schema || !$phenome_schema) { die "Need metadata schema parameter\n"; }
1857 my $trial_id = $self->get_trial_id();
1859 #print STDERR "Deleting metadata for trial $trial_id...\n";
1861 # first, deal with entries in the md_metadata table, which may reference nd_experiment (through linking table)
1863 my $q = "SELECT distinct(metadata_id) FROM nd_experiment_project JOIN nd_experiment_phenotype USING(nd_experiment_id) LEFT JOIN phenome.nd_experiment_md_files ON (nd_experiment_phenotype.nd_experiment_id=nd_experiment_md_files.nd_experiment_id) LEFT JOIN metadata.md_files using(file_id) LEFT JOIN metadata.md_metadata using(metadata_id) WHERE project_id=?";
1864 my $h = $self->bcs_schema->storage()->dbh()->prepare($q);
1865 $h->execute($trial_id);
1867 while (my ($md_id) = $h->fetchrow_array()) {
1868 #print STDERR "Associated metadata id: $md_id\n";
1869 my $mdmd_row = $metadata_schema->resultset("MdMetadata")->find( { metadata_id => $md_id } );
1870 if ($mdmd_row) {
1871 #print STDERR "Obsoleting $md_id...\n";
1873 $mdmd_row -> update( { obsolete => 1 });
1877 #print STDERR "Deleting the entries in the linking table...\n";
1879 # delete the entries from the linking table...
1880 $q = "SELECT distinct(file_id) FROM nd_experiment_project JOIN nd_experiment_phenotype USING(nd_experiment_id) JOIN phenome.nd_experiment_md_files ON (nd_experiment_phenotype.nd_experiment_id=nd_experiment_md_files.nd_experiment_id) LEFT JOIN metadata.md_files using(file_id) LEFT JOIN metadata.md_metadata using(metadata_id) WHERE project_id=?";
1881 $h = $self->bcs_schema->storage()->dbh()->prepare($q);
1882 $h->execute($trial_id);
1884 while (my ($file_id) = $h->fetchrow_array()) {
1885 print STDERR "trying to delete association for file with id $file_id...\n";
1886 my $ndemdf_rs = $phenome_schema->resultset("NdExperimentMdFiles")->search( { file_id=>$file_id });
1887 print STDERR "Deleting md_files linking table entries...\n";
1888 foreach my $row ($ndemdf_rs->all()) {
1889 print STDERR "DELETING !!!!\n";
1890 $row->delete();
1897 =head2 function delete_metadata()
1899 Usage: $trial->delete_metadata();
1900 Desc: obsoletes the metadata entries for this trial.
1901 Ret:
1902 Args:
1903 Side Effects:
1904 Example:
1906 =cut
1908 sub delete_metadata {
1909 my $self = shift;
1910 my $metadata_schema = $self->metadata_schema;
1911 my $phenome_schema = $self->phenome_schema;
1913 if (!$metadata_schema || !$phenome_schema) { die "Need metadata schema parameter\n"; }
1915 my $trial_id = $self->get_trial_id();
1917 if (scalar(@{$self->get_genotyping_trials_from_field_trial}) > 0) {
1918 return 'This field trial has been linked to genotyping trials already, and cannot be easily deleted.';
1920 if (scalar(@{$self->get_field_trials_source_of_genotyping_trial}) > 0) {
1921 return 'This genotyping trial has been linked to field trials already, and cannot be easily deleted.';
1923 if (scalar(@{$self->get_crossing_trials_from_field_trial}) >0) {
1924 return 'This field trial has been linked to crossing trials already, and cannot be easily deleted.';
1926 if (scalar(@{$self->get_field_trials_source_of_crossing_trial}) >0) {
1927 return 'This crossing trial has been linked to field trials already, and cannot be easily deleted.';
1930 #print STDERR "Deleting metadata for trial $trial_id...\n";
1932 # first, deal with entries in the md_metadata table, which may reference nd_experiment (through linking table)
1934 my $q = "SELECT distinct(metadata_id) FROM nd_experiment_project JOIN phenome.nd_experiment_md_files using(nd_experiment_id) LEFT JOIN metadata.md_files using(file_id) LEFT JOIN metadata.md_metadata using(metadata_id) WHERE project_id=?";
1935 my $h = $self->bcs_schema->storage()->dbh()->prepare($q);
1936 $h->execute($trial_id);
1938 while (my ($md_id) = $h->fetchrow_array()) {
1939 #print STDERR "Associated metadata id: $md_id\n";
1940 my $mdmd_row = $metadata_schema->resultset("MdMetadata")->find( { metadata_id => $md_id } );
1941 if ($mdmd_row) {
1942 #print STDERR "Obsoleting $md_id...\n";
1944 $mdmd_row -> update( { obsolete => 1 });
1948 #print STDERR "Deleting the entries in the linking table...\n";
1950 # delete the entries from the linking table... (left joins are due to sometimes missing md_file entries)
1951 $q = "SELECT distinct(file_id) FROM nd_experiment_project LEFT JOIN phenome.nd_experiment_md_files using(nd_experiment_id) LEFT JOIN metadata.md_files using(file_id) LEFT JOIN metadata.md_metadata using(metadata_id) WHERE project_id=?";
1952 $h = $self->bcs_schema->storage()->dbh()->prepare($q);
1953 $h->execute($trial_id);
1955 while (my ($file_id) = $h->fetchrow_array()) {
1956 print STDERR "trying to delete association for file with id $file_id...\n";
1957 my $ndemdf_rs = $phenome_schema->resultset("NdExperimentMdFiles")->search( { file_id=>$file_id });
1958 print STDERR "Deleting md_files linking table entries...\n";
1959 foreach my $row ($ndemdf_rs->all()) {
1960 print STDERR "DELETING !!!!\n";
1961 $row->delete();
1967 sub _delete_field_layout_experiment {
1968 my $self = shift;
1970 my $trial_id = $self->get_trial_id();
1972 print STDERR "_delete_field_layout_experiment...\n";
1974 # check if there are still associated phenotypes...
1976 if ($self->phenotype_count() > 0) {
1977 print STDERR "Attempt to delete field layout that still has associated phenotype data.\n";
1978 die "cannot delete because of associated phenotypes\n";
1979 return { error => "Trial still has associated phenotyping experiment, cannot delete." };
1982 my $field_layout_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'field_layout', 'experiment_type')->cvterm_id();
1983 my $genotyping_layout_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'genotyping_layout', 'experiment_type')->cvterm_id();
1985 my $layout_design = $self->get_layout->get_design;
1986 my @all_stock_ids;
1987 while( my($plot_num, $design_info) = each %$layout_design){
1988 my $plot_id = $design_info->{plot_id}; #this includes the "tissue_sample" in "genotyping_layout"
1989 my @plant_ids = $design_info->{plant_ids} ? @{$design_info->{plant_ids}} : ();
1990 my @subplot_ids = $design_info->{subplot_ids} ? @{$design_info->{subplot_ids}} : ();
1991 my @tissue_sample_ids = $design_info->{tissue_sample_ids} ? @{$design_info->{tissue_sample_ids}} : ();
1992 push @all_stock_ids, $plot_id;
1993 push @all_stock_ids, @plant_ids;
1994 push @all_stock_ids, @subplot_ids;
1995 push @all_stock_ids, @tissue_sample_ids;
1998 #print STDERR Dumper \@all_stock_ids;
1999 my $stock_delete_rs = $self->bcs_schema->resultset('Stock::Stock')->search({stock_id=>{'-in'=>\@all_stock_ids}});
2000 while (my $r = $stock_delete_rs->next){
2001 $r->delete();
2004 my $has_plants = $self->has_plant_entries();
2005 my $has_subplots = $self->has_subplot_entries();
2006 my $has_tissues = $self->has_tissue_sample_entries();
2008 if ($has_plants) {
2009 my $has_plants_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project_has_plant_entries', 'project_property' )->cvterm_id();
2010 my $has_plants_prop = $self->bcs_schema->resultset("Project::Projectprop")->find({ type_id => $has_plants_cvterm_id, project_id => $trial_id });
2011 $has_plants_prop->delete();
2013 if ($has_subplots) {
2014 my $has_subplots_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project_has_subplot_entries', 'project_property' )->cvterm_id();
2015 my $has_subplots_prop = $self->bcs_schema->resultset("Project::Projectprop")->find({ type_id => $has_subplots_cvterm_id, project_id => $trial_id });
2016 $has_subplots_prop->delete();
2018 if ($has_tissues) {
2019 my $has_tissues_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project_has_tissue_sample_entries', 'project_property' )->cvterm_id();
2020 my $has_tissues_prop = $self->bcs_schema->resultset("Project::Projectprop")->find({ type_id => $has_tissues_cvterm_id, project_id => $trial_id });
2021 $has_tissues_prop->delete();
2024 my $trial_layout_json_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'trial_layout_json', 'project_property')->cvterm_id();
2025 my $has_cached_layout_prop = $self->bcs_schema->resultset("Project::Projectprop")->find({ type_id => $trial_layout_json_cvterm_id, project_id => $trial_id });
2026 if ($has_cached_layout_prop){
2027 $has_cached_layout_prop->delete();
2030 my $nde_rs = $self->bcs_schema()->resultset("NaturalDiversity::NdExperiment")->search({ 'me.type_id'=>[$field_layout_type_id, $genotyping_layout_type_id], 'project.project_id'=>$trial_id }, {'join'=>{'nd_experiment_projects'=>'project'}});
2031 if ($nde_rs->count != 1){
2032 die "Project $trial_id does not have exactly one ndexperiment of type field_layout or genotyping_layout!"
2034 while( my $r = $nde_rs->next){
2035 $r->delete();
2038 #return { success => $plots_deleted };
2039 return { success => 1 };
2042 sub _delete_management_factors_experiments {
2043 my $self = shift;
2044 my $management_factor_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'treatment_experiment', 'experiment_type')->cvterm_id();
2045 my $management_factors = $self->get_treatments;
2046 foreach (@$management_factors){
2047 my $m = CXGN::Trial->new({
2048 bcs_schema => $self->bcs_schema,
2049 metadata_schema => $self->metadata_schema,
2050 phenome_schema => $self->phenome_schema,
2051 trial_id => $_->[0]
2053 my $nde_rs = $self->bcs_schema()->resultset("NaturalDiversity::NdExperiment")->search({ 'me.type_id'=>$management_factor_type_id, 'project.project_id'=>$m->get_trial_id }, {'join'=>{'nd_experiment_projects'=>'project'}});
2054 if ($nde_rs->count != 1){
2055 die "Management factor ".$m->get_name." does not have exactly one ndexperiment of type treatment_experiment!"
2057 while( my $r = $nde_rs->next){
2058 $r->delete();
2060 $m->delete_project_entry;
2062 return { success => 1 };
2065 =head2 function delete_project_entry()
2067 Usage:
2068 Desc:
2069 Ret:
2070 Args:
2071 Side Effects:
2072 Example:
2074 =cut
2076 sub delete_project_entry {
2077 my $self = shift;
2079 if ($self->phenotype_count() > 0) {
2080 print STDERR "Cannot delete trial with associated phenotypes.\n";
2081 return;
2084 if (scalar(@{$self->get_genotyping_trials_from_field_trial}) > 0) {
2085 return 'This field trial has been linked to genotyping trials already, and cannot be easily deleted.';
2087 if (scalar(@{$self->get_field_trials_source_of_genotyping_trial}) > 0) {
2088 return 'This genotyping trial has been linked to field trials already, and cannot be easily deleted.';
2090 if (scalar(@{$self->get_crossing_trials_from_field_trial}) >0) {
2091 return 'This field trial has been linked to crossing trials already, and cannot be easily deleted.';
2093 if (scalar(@{$self->get_field_trials_source_of_crossing_trial}) >0) {
2094 return 'This crossing trial has been linked to field trials already, and cannot be easily deleted.';
2097 eval {
2098 my $row = $self->bcs_schema->resultset("Project::Project")->find( { project_id=> $self->get_trial_id() });
2099 $row->delete();
2100 print STDERR "deleted project ".$self->get_trial_id."\n";
2102 if ($@) {
2103 print STDERR "An error occurred during deletion: $@\n";
2104 return $@;
2108 =head2 function phenotype_count()
2110 Usage:
2111 Desc: The number of phenotype measurements associated with this trial
2112 Ret:
2113 Args:
2114 Side Effects:
2115 Example:
2117 =cut
2120 sub phenotype_count {
2121 my $self = shift;
2122 my $phenotyping_experiment_type_id = $self->bcs_schema->resultset("Cv::Cvterm")->find( { name => 'phenotyping_experiment' })->cvterm_id();
2124 my $q = "SELECT count(phenotype_id)
2125 FROM phenotype
2126 JOIN nd_experiment_phenotype using(phenotype_id)
2127 JOIN nd_experiment_project using(nd_experiment_id)
2128 JOIN nd_experiment using(nd_experiment_id)
2129 JOIN project using(project_id)
2130 WHERE nd_experiment.type_id = $phenotyping_experiment_type_id
2131 AND project_id = ?;";
2132 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
2133 $h->execute($self->get_trial_id());
2134 my ($count) = $h->fetchrow_array();
2135 return $count;
2139 =head2 function total_phenotypes()
2141 Usage:
2142 Desc: returns the total number of phenotype measurements
2143 associated with the trial
2144 Ret:
2145 Args:
2146 Side Effects:
2147 Example:
2149 =cut
2151 sub total_phenotypes {
2152 my $self = shift;
2154 my $pt_rs = $self->bcs_schema()->resultset("Phenotype::Phenotype")->search( { });
2155 return $pt_rs->count();
2158 =head2 function add_additional_uploaded_file()
2160 Usage: $trial->add_additional_uploaded_file();
2161 Desc: adds metadata.md_file entry for additional_files_uploaded to trial
2162 Ret:
2163 Args:
2164 Side Effects:
2165 Example:
2167 =cut
2169 sub add_additional_uploaded_file {
2170 my $self = shift;
2171 my $user_id = shift;
2172 my $archived_filename_with_path = shift;
2173 my $md5checksum = shift;
2174 my $result = $self->get_nd_experiment_id();
2175 if ($result->{error}){
2176 return {error => $result->{error} };
2178 my $nd_experiment_id = $result->{nd_experiment_id};
2180 my $md_row = $self->metadata_schema->resultset("MdMetadata")->create({create_person_id => $user_id});
2181 $md_row->insert();
2182 my $file_row = $self->metadata_schema->resultset("MdFiles")
2183 ->create({
2184 basename => basename($archived_filename_with_path),
2185 dirname => dirname($archived_filename_with_path),
2186 filetype => 'trial_additional_file_upload',
2187 md5checksum => $md5checksum,
2188 metadata_id => $md_row->metadata_id(),
2190 my $file_id = $file_row->file_id();
2191 my $experiment_file = $self->phenome_schema->resultset("NdExperimentMdFiles")
2192 ->create({
2193 nd_experiment_id => $nd_experiment_id,
2194 file_id => $file_id,
2197 return {success => 1, file_id=>$file_id};
2200 =head2 function get_additional_uploaded_files()
2202 Usage: $trial->get_additional_uploaded_files();
2203 Desc: retrieves metadata.md_file entries for additional_files_uploaded to trial. these entries are created from add_additional_uploaded_file
2204 Ret:
2205 Args:
2206 Side Effects:
2207 Example:
2209 =cut
2211 sub get_additional_uploaded_files {
2212 my $self = shift;
2213 my $trial_id = $self->get_trial_id();
2214 my @file_array;
2215 my %file_info;
2216 my $q = "SELECT file_id, m.create_date, p.sp_person_id, p.username, basename, dirname, filetype FROM project JOIN nd_experiment_project USING(project_id) JOIN phenome.nd_experiment_md_files ON (nd_experiment_project.nd_experiment_id=nd_experiment_md_files.nd_experiment_id) LEFT JOIN metadata.md_files using(file_id) LEFT JOIN metadata.md_metadata as m using(metadata_id) LEFT JOIN sgn_people.sp_person as p ON (p.sp_person_id=m.create_person_id) WHERE project_id=? and m.obsolete = 0 and metadata.md_files.filetype='trial_additional_file_upload' ORDER BY file_id ASC";
2217 my $h = $self->bcs_schema->storage()->dbh()->prepare($q);
2218 $h->execute($trial_id);
2220 while (my ($file_id, $create_date, $person_id, $username, $basename, $dirname, $filetype) = $h->fetchrow_array()) {
2221 $file_info{$file_id} = [$file_id, $create_date, $person_id, $username, $basename, $dirname, $filetype];
2223 foreach (keys %file_info){
2224 push @file_array, $file_info{$_};
2226 return \@file_array;
2229 =head2 function get_phenotypes_for_trait($trait_id)
2231 Usage:
2232 Desc: returns the measurements for the given trait in this trial as an array of values, e.g. [2.1, 2, 50]
2233 Ret:
2234 Args:
2235 Side Effects:
2236 Example:
2238 =cut
2240 sub get_phenotypes_for_trait {
2241 my $self = shift;
2242 my $trait_id = shift;
2243 my $stock_type = shift;
2244 my @data;
2245 my $dbh = $self->bcs_schema->storage()->dbh();
2246 #my $schema = $self->bcs_schema();
2248 my $h;
2249 my $join_string = '';
2250 my $where_string = '';
2251 if ($stock_type) {
2252 my $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, $stock_type, 'stock_type')->cvterm_id();
2253 $join_string = 'JOIN nd_experiment_stock USING(nd_experiment_id) JOIN stock USING(stock_id)';
2254 $where_string = "stock.type_id=$stock_type_id and";
2256 my $q = "SELECT phenotype.value::real FROM cvterm JOIN phenotype ON (cvterm_id=cvalue_id) JOIN nd_experiment_phenotype USING(phenotype_id) JOIN nd_experiment_project USING(nd_experiment_id) $join_string WHERE $where_string project_id=? and cvterm.cvterm_id = ? and phenotype.value~? ORDER BY phenotype_id ASC;";
2257 $h = $dbh->prepare($q);
2259 my $numeric_regex = '^-?[0-9]+([,.][0-9]+)?$';
2260 $h->execute($self->get_trial_id(), $trait_id, $numeric_regex );
2261 while (my ($value) = $h->fetchrow_array()) {
2262 push @data, $value + 0;
2264 return @data;
2267 =head2 function get_stock_phenotypes_for_traits(\@trait_id, 'all', ['plot_of','plant_of'], 'accession', 'subject')
2269 Usage:
2270 Desc: returns all observations for the given traits in this trial
2271 Ret: arrayref of [[ $stock_id, $stock_name, $trait_id, $trait_name, $phenotype_id, $pheno_uniquename, $uploader_id, $value, $rel_stock_id, $rel_stock_name ], [], ...]
2272 Args: trait_ids : arrayref of cvterm_ids
2273 stock_type: the stock type that the phenotype is associated to. 'plot', or 'plant', or 'all'
2274 stock_relationships: for fetching stock_relationships of the phenotyped stock. arrayref of relationships. e.g. ['plot_of', 'plant_of'].
2275 relationship_stock_type: the associated stock_type from the stock_relationship. 'plot', or 'plant'
2276 subject_or_object: whether the stock_relationship join should be done from the subject or object side. 'subject', or 'object'
2277 Side Effects:
2278 Example:
2280 =cut
2282 sub get_stock_phenotypes_for_traits {
2283 my $self = shift;
2284 my $trait_ids = shift;
2285 my $stock_type = shift; #plot, plant, all
2286 my $stock_relationships = shift; #arrayref. plot_of, plant_of
2287 my $relationship_stock_type = shift; #plot, plant
2288 my $subject_or_object = shift;
2289 my @data;
2290 #$self->bcs_schema->storage->debug(1);
2291 my $dbh = $self->bcs_schema->storage()->dbh();
2292 my $where_clause = "WHERE project_id=? and b.cvterm_id = ? and phenotype.value~? ";
2293 my $phenotyping_experiment_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'phenotyping_experiment', 'experiment_type')->cvterm_id();
2295 if (scalar(@$trait_ids)>0){
2296 my $sql_trait_ids = join ("," , @$trait_ids);
2297 $where_clause .= "and a.cvterm_id IN ($sql_trait_ids) ";
2300 my $relationship_join = '';
2301 if ($subject_or_object eq 'object') {
2302 $relationship_join = 'JOIN stock_relationship on (stock.stock_id=stock_relationship.object_id) JOIN stock as rel_stock on (stock_relationship.subject_id=rel_stock.stock_id) ';
2303 } elsif ($subject_or_object eq 'subject') {
2304 $relationship_join = 'JOIN stock_relationship on (stock.stock_id=stock_relationship.subject_id) JOIN stock as rel_stock on (stock_relationship.object_id=rel_stock.stock_id) ';
2306 if ($stock_type ne 'all') {
2307 my $stock_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), $stock_type, 'stock_type')->cvterm_id();
2308 $where_clause .= "and stock.type_id=$stock_type_cvterm_id ";
2310 my @stock_rel_or;
2311 foreach (@$stock_relationships) {
2312 my $stock_relationship_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), $_, 'stock_relationship')->cvterm_id();
2313 push @stock_rel_or, "stock_relationship.type_id=$stock_relationship_cvterm_id";
2315 my $stock_rel_or_sql = join (" OR " , @stock_rel_or);
2316 if ($stock_rel_or_sql) {
2317 $where_clause .= "and ($stock_rel_or_sql) ";
2319 my $rel_stock_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), $relationship_stock_type, 'stock_type')->cvterm_id();
2320 $where_clause .= "and rel_stock.type_id=$rel_stock_type_cvterm_id ";
2322 my $q = "SELECT stock.stock_id, stock.uniquename, a.cvterm_id, a.name || '|' || db.name || ':' || dbxref.accession, phenotype.phenotype_id, phenotype.uniquename, phenotype.sp_person_id, phenotype.value::real, rel_stock.stock_id, rel_stock.uniquename, stock_type.name
2323 FROM cvterm as a
2324 JOIN dbxref ON (a.dbxref_id = dbxref.dbxref_id)
2325 JOIN db USING(db_id)
2326 JOIN phenotype ON (a.cvterm_id=cvalue_id)
2327 JOIN nd_experiment_phenotype USING(phenotype_id)
2328 JOIN nd_experiment_project USING(nd_experiment_id)
2329 JOIN nd_experiment_stock USING(nd_experiment_id)
2330 JOIN cvterm as b ON (b.cvterm_id=nd_experiment_stock.type_id)
2331 JOIN stock USING(stock_id)
2332 JOIN cvterm as stock_type ON (stock_type.cvterm_id=stock.type_id)
2333 $relationship_join
2334 $where_clause
2335 ORDER BY stock.stock_id;";
2337 print STDERR "QUERY = $q\n";
2338 my $h = $dbh->prepare($q);
2340 my $numeric_regex = '^-?[0-9]+([,.][0-9]+)?$';
2341 $h->execute($self->get_trial_id(), $phenotyping_experiment_cvterm, $numeric_regex );
2342 while (my ($stock_id, $stock_name, $trait_id, $trait_name, $phenotype_id, $pheno_uniquename, $uploader_id, $value, $rel_stock_id, $rel_stock_name, $stock_type) = $h->fetchrow_array()) {
2343 push @data, [$stock_id, $stock_name, $trait_id, $trait_name, $phenotype_id, $pheno_uniquename, $uploader_id, $value + 0, $rel_stock_id, $rel_stock_name, $stock_type];
2345 return \@data;
2348 =head2 function get_traits_assayed()
2350 Usage:
2351 Desc: returns the cvterm_id and name for traits assayed
2352 Ret:
2353 Args: stock_type can be the cvterm name for a specific stock type like 'plot'. not providing stock_type will return all traits assayed in the trial. trait_format can be for only returning numeric, categorical, etc traits. not providing trait_format will return all trait types.
2354 Side Effects:
2355 Example:
2357 =cut
2359 sub get_traits_assayed {
2360 my $self = shift;
2361 my $stock_type = shift;
2362 my $trait_format = shift;
2363 my $contains_composable_cv_type = shift;
2364 my $schema = $self->bcs_schema;
2365 my $dbh = $self->bcs_schema->storage()->dbh();
2367 my @traits_assayed;
2369 my $cvtermprop_join = '';
2370 my $cvtermprop_where = '';
2371 if ($trait_format){
2372 my $trait_format_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), 'trait_format', 'trait_property')->cvterm_id();
2373 $cvtermprop_join = ' JOIN cvtermprop ON (cvtermprop.cvterm_id = cvterm.cvterm_id) ';
2374 $cvtermprop_where = " AND cvtermprop.type_id = $trait_format_cvterm_id AND cvtermprop.value = '$trait_format' ";
2377 my $contains_relationship_rs = $schema->resultset("Cv::Cvterm")->search({ name => 'contains' });
2378 if ($contains_relationship_rs->count == 0) {
2379 die "The cvterm 'contains' was not found! Please add this cvterm! Generally this term is added when loading an ontology into the database.\n";
2381 elsif ($contains_relationship_rs->count > 1) {
2382 die "The cvterm 'contains' was found more than once! Please consolidate this cvterm by updating cvterm_relationship entries and then deleting the left over cvterm entry! Generally this term is added when loading an ontology into the database.\n";
2384 my $contains_relationship_cvterm_id = $contains_relationship_rs->first->cvterm_id;
2385 my $variable_relationship_rs = $schema->resultset("Cv::Cvterm")->search({ name => 'VARIABLE_OF' });
2386 if ($variable_relationship_rs->count == 0) {
2387 die "The cvterm 'VARIABLE_OF' was not found! Please add this cvterm! Generally this term is added when loading an ontology into the database.\n";
2389 elsif ($variable_relationship_rs->count > 1) {
2390 die "The cvterm 'VARIABLE_OF' was found more than once! Please consolidate this cvterm by updating cvterm_relationship entries and then deleting the left over cvterm entry! Generally this term is added when loading an ontology into the database.\n";
2393 my $composable_cv_type_cvterm_id = $contains_composable_cv_type ? SGN::Model::Cvterm->get_cvterm_row($schema, $contains_composable_cv_type, 'composable_cvtypes')->cvterm_id : '';
2395 my $q;
2396 if ($stock_type) {
2397 my $stock_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema(), $stock_type, 'stock_type')->cvterm_id();
2398 $q = "SELECT (((cvterm.name::text || '|'::text) || db.name::text) || ':'::text) || dbxref.accession::text AS trait, cvterm.cvterm_id, imaging_project.project_id, imaging_project.name, count(phenotype.value)
2399 FROM cvterm
2400 $cvtermprop_join
2401 JOIN dbxref ON (cvterm.dbxref_id = dbxref.dbxref_id)
2402 JOIN db ON (dbxref.db_id = db.db_id)
2403 JOIN phenotype ON (cvterm.cvterm_id=phenotype.cvalue_id)
2404 JOIN nd_experiment_phenotype USING(phenotype_id)
2405 JOIN nd_experiment_project USING(nd_experiment_id)
2406 JOIN nd_experiment_stock USING(nd_experiment_id)
2407 LEFT JOIN phenome.nd_experiment_md_images AS nd_experiment_md_images USING(nd_experiment_id)
2408 LEFT JOIN phenome.project_md_image AS project_md_image ON (nd_experiment_md_images.image_id=project_md_image.image_id)
2409 LEFT JOIN project AS imaging_project ON (project_md_image.project_id=imaging_project.project_id)
2410 JOIN stock on (stock.stock_id = nd_experiment_stock.stock_id)
2411 WHERE stock.type_id=$stock_type_cvterm_id and nd_experiment_project.project_id=? $cvtermprop_where
2412 GROUP BY trait, cvterm.cvterm_id, imaging_project.project_id, imaging_project.name
2413 ORDER BY trait;";
2414 } else {
2415 $q = "SELECT (((cvterm.name::text || '|'::text) || db.name::text) || ':'::text) || dbxref.accession::text AS trait, cvterm.cvterm_id, imaging_project.project_id, imaging_project.name, count(phenotype.value)
2416 FROM cvterm
2417 $cvtermprop_join
2418 JOIN dbxref ON (cvterm.dbxref_id = dbxref.dbxref_id)
2419 JOIN db ON (dbxref.db_id = db.db_id)
2420 JOIN phenotype ON (cvterm.cvterm_id=phenotype.cvalue_id)
2421 JOIN nd_experiment_phenotype USING(phenotype_id)
2422 JOIN nd_experiment_project USING(nd_experiment_id)
2423 LEFT JOIN phenome.nd_experiment_md_images AS nd_experiment_md_images USING(nd_experiment_id)
2424 LEFT JOIN phenome.project_md_image AS project_md_image ON (nd_experiment_md_images.image_id=project_md_image.image_id)
2425 LEFT JOIN project AS imaging_project ON (project_md_image.project_id=imaging_project.project_id)
2426 WHERE nd_experiment_project.project_id=? $cvtermprop_where
2427 GROUP BY trait, cvterm.cvterm_id, imaging_project.project_id, imaging_project.name
2428 ORDER BY trait;";
2431 my $component_q = "SELECT COALESCE(
2432 json_agg(json_build_object('cvterm_id', component_cvterm.cvterm_id, 'name', component_cvterm.name, 'definition', component_cvterm.definition, 'cv_name', cv.name, 'cv_type', cv_type.name, 'cv_type_cvterm_id', cv_type.cvterm_id))
2433 FILTER (WHERE component_cvterm.cvterm_id IS NOT NULL), '[]'
2434 ) AS components
2435 FROM cvterm
2436 LEFT JOIN cvterm_relationship on (cvterm.cvterm_id = cvterm_relationship.object_id AND cvterm_relationship.type_id = $contains_relationship_cvterm_id)
2437 LEFT JOIN cvterm AS component_cvterm on (cvterm_relationship.subject_id = component_cvterm.cvterm_id)
2438 LEFT JOIN cv on (component_cvterm.cv_id = cv.cv_id)
2439 LEFT JOIN cvprop on (cv.cv_id = cvprop.cv_id)
2440 LEFT JOIN cvterm AS cv_type on (cv_type.cvterm_id = cvprop.type_id)
2441 WHERE cvterm.cvterm_id=? ;";
2443 print STDERR Dumper $q;
2445 my $traits_assayed_h = $dbh->prepare($q);
2446 my $component_h = $dbh->prepare($component_q);
2448 $traits_assayed_h->execute($self->get_trial_id());
2449 while (my ($trait_name, $trait_id, $imaging_project_id, $imaging_project_name, $count) = $traits_assayed_h->fetchrow_array()) {
2450 $component_h->execute($trait_id);
2451 my ($component_terms) = $component_h->fetchrow_array();
2452 $component_terms = decode_json $component_terms;
2453 if ($contains_composable_cv_type) {
2454 my $has_composable_cv_type = 0;
2455 foreach (@$component_terms) {
2456 if ($_->{cv_type_cvterm_id} && $_->{cv_type_cvterm_id} == $composable_cv_type_cvterm_id) {
2457 $has_composable_cv_type = 1;
2460 if ($has_composable_cv_type == 1) {
2461 push @traits_assayed, [$trait_id, $trait_name, $component_terms, $count, $imaging_project_id, $imaging_project_name];
2464 else {
2465 push @traits_assayed, [$trait_id, $trait_name, $component_terms, $count, $imaging_project_id, $imaging_project_name];
2468 return \@traits_assayed;
2471 =head2 function get_trait_components_assayed()
2473 Usage:
2474 Desc: returns the cvterm_id and name for trait components assayed
2475 Ret:
2476 Args:
2477 Side Effects:
2478 Example:
2480 =cut
2482 sub get_trait_components_assayed {
2483 my $self = shift;
2484 my $stock_type = shift;
2485 my $composable_cvterm_format = shift;
2486 my $dbh = $self->bcs_schema->storage()->dbh();
2487 my $traits_assayed = $self->get_traits_assayed($stock_type);
2489 my %unique_components;
2490 my @trait_components_assayed;
2491 foreach (@$traits_assayed){
2492 my $trait_components = SGN::Model::Cvterm->get_components_from_trait($self->bcs_schema, $_->[0]);
2493 foreach (@$trait_components){
2494 if (!exists($unique_components{$_})){
2495 my $component_cvterm = SGN::Model::Cvterm::get_trait_from_cvterm_id($self->bcs_schema, $_, $composable_cvterm_format);
2496 push @trait_components_assayed, [$_, $component_cvterm];
2497 $unique_components{$_}++;
2501 return \@trait_components_assayed;
2504 =head2 function get_experiment_count()
2506 Usage:
2507 Desc: return the total number of experiments associated
2508 with the trial.
2509 Ret:
2510 Args:
2511 Side Effects:
2512 Example:
2514 =cut
2516 sub get_experiment_count {
2517 my $self = shift;
2519 my $rs = $self->bcs_schema->resultset('NaturalDiversity::NdExperimentProject')->search( { project_id => $self->get_trial_id() });
2520 return $rs->count();
2523 sub get_location_type_id {
2524 my $self = shift;
2525 my $rs = $self->bcs_schema->resultset('Cv::Cvterm')->search( { name => 'project location' });
2527 if ($rs->count() > 0) {
2528 return $rs->first()->cvterm_id();
2533 sub get_year_type_id {
2534 my $self = shift;
2536 my $rs = $self->bcs_schema->resultset('Cv::Cvterm')->search( { name => 'project year' });
2538 return $rs->first()->cvterm_id();
2541 sub get_breeding_program_trial_relationship_cvterm_id {
2542 my $self = shift;
2544 my $breeding_program_trial_relationship_cvterm_id;
2545 my $breeding_program_trial_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'breeding_program_trial_relationship', 'project_relationship');
2546 if ($breeding_program_trial_relationship_cvterm) {
2547 $breeding_program_trial_relationship_cvterm_id = $breeding_program_trial_relationship_cvterm->cvterm_id();
2550 return $breeding_program_trial_relationship_cvterm_id;
2553 sub get_breeding_program_cvterm_id {
2554 my $self = shift;
2556 my $breeding_program_cvterm_id;
2557 my $breeding_program_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'breeding_program', 'project_property');
2558 if ($breeding_program_cvterm) {
2559 $breeding_program_cvterm_id = $breeding_program_cvterm->cvterm_id();
2562 return $breeding_program_cvterm_id;
2565 sub get_folder {
2566 my $self = shift;
2568 my $f = CXGN::Trial::Folder->new( { bcs_schema => $self->bcs_schema(), folder_id => $self->get_trial_id() });
2570 my $parent_folder_data = $f->project_parent();
2572 if ($parent_folder_data) {
2573 return $parent_folder_data;
2575 else {
2576 return;
2580 sub get_harvest_date_cvterm_id {
2581 my $self = shift;
2583 my $harvest_date_cvterm_id;
2584 my $harvest_date_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project_harvest_date', 'project_property');
2585 if ($harvest_date_cvterm) {
2586 $harvest_date_cvterm_id = $harvest_date_cvterm->cvterm_id();
2589 return $harvest_date_cvterm_id;
2593 sub get_project_start_date_cvterm_id {
2594 my $self = shift;
2596 my $start_date_cvterm_id;
2597 my $start_date_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project_start_date', 'project_property');
2598 if ($start_date_cvterm) {
2599 $start_date_cvterm_id = $start_date_cvterm->cvterm_id();
2602 return $start_date_cvterm_id;
2605 =head2 function create_plant_entities()
2607 Usage: $trial->create_plant_entries($plants_per_plot);
2608 Desc: Some trials require plant-level data. This function will
2609 add an additional layer of plant entries for each plot.
2610 Ret:
2611 Args: the number of plants per plot to add.
2612 Side Effects:
2613 Example:
2615 =cut
2617 sub create_plant_entities {
2618 my $self = shift;
2619 my $plants_per_plot = shift || 30;
2620 my $inherits_plot_treatments = shift;
2622 my $create_plant_entities_txn = sub {
2623 my $chado_schema = $self->bcs_schema();
2624 my $layout = CXGN::Trial::TrialLayout->new( { schema => $chado_schema, trial_id => $self->get_trial_id(), experiment_type=>'field_layout' });
2625 my $design = $layout->get_design();
2627 my $accession_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'accession', 'stock_type')->cvterm_id();
2628 my $cross_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'cross', 'stock_type')->cvterm_id();
2629 my $family_name_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'family_name', 'stock_type')->cvterm_id();
2630 my $plant_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant', 'stock_type')->cvterm_id();
2631 my $plot_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot', 'stock_type')->cvterm_id();
2632 my $plot_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot_of', 'stock_relationship')->cvterm_id();
2633 my $plant_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_of', 'stock_relationship')->cvterm_id();
2634 my $plant_index_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_index_number', 'stock_property')->cvterm_id();
2635 my $block_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'block', 'stock_property')->cvterm_id();
2636 my $plot_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot number', 'stock_property')->cvterm_id();
2637 my $replicate_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'replicate', 'stock_property')->cvterm_id();
2638 my $has_plants_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_plant_entries', 'project_property')->cvterm_id();
2639 my $field_layout_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'field_layout', 'experiment_type')->cvterm_id();
2640 my $treatment_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'treatment_experiment', 'experiment_type')->cvterm_id();
2641 #my $plants_per_plot_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plants_per_plot', 'project_property')->cvterm_id();
2643 my $treatments;
2644 my %treatment_experiments;
2645 my %treatment_plots;
2646 if ($inherits_plot_treatments){
2647 $treatments = $self->get_treatments();
2648 foreach (@$treatments){
2650 my $rs = $chado_schema->resultset("Project::Projectprop")->find_or_create({
2651 type_id => $has_plants_cvterm,
2652 value => $plants_per_plot,
2653 project_id => $_->[0],
2656 my $treatment_nd_experiment = $chado_schema->resultset("Project::Project")->search( { 'me.project_id' => $_->[0] }, {select=>['nd_experiment.nd_experiment_id']})->search_related('nd_experiment_projects')->search_related('nd_experiment', { type_id => $treatment_cvterm })->single();
2657 $treatment_experiments{$_->[0]} = $treatment_nd_experiment->nd_experiment_id();
2659 my $treatment_trial = CXGN::Project->new({ bcs_schema => $chado_schema, trial_id => $_->[0]});
2660 my $plots = $treatment_trial->get_plots();
2661 foreach my $plot (@$plots){
2662 $treatment_plots{$_->[0]}->{$plot->[0]} = 1;
2667 my $rs = $chado_schema->resultset("Project::Projectprop")->find_or_create({
2668 type_id => $has_plants_cvterm,
2669 value => $plants_per_plot,
2670 project_id => $self->get_trial_id(),
2673 my $field_layout_experiment = $chado_schema->resultset("Project::Project")->search( { 'me.project_id' => $self->get_trial_id() }, {select=>['nd_experiment.nd_experiment_id']})->search_related('nd_experiment_projects')->search_related('nd_experiment', { type_id => $field_layout_cvterm })->single();
2675 foreach my $plot (keys %$design) {
2676 print STDERR " ... creating plants for plot $plot...\n";
2677 my $plot_row = $chado_schema->resultset("Stock::Stock")->find( { uniquename => $design->{$plot}->{plot_name}, type_id=>$plot_cvterm });
2679 if (! $plot_row) {
2680 print STDERR "The plot $plot is not found in the database\n";
2681 return "The plot $plot is not yet in the database. Cannot create plant entries.";
2684 my $parent_plot = $plot_row->stock_id();
2685 my $parent_plot_name = $plot_row->uniquename();
2686 my $parent_plot_organism = $plot_row->organism_id();
2688 foreach my $plant_index_number (1..$plants_per_plot) {
2689 my $plant_name = $parent_plot_name."_plant_$plant_index_number";
2690 #print STDERR "... ... creating plant $plant_name...\n";
2692 $self->_save_plant_entry($chado_schema, $accession_cvterm, $cross_cvterm, $family_name_cvterm, $parent_plot_organism, $parent_plot_name, $parent_plot, $plant_name, $plant_cvterm, $plant_index_number, $plant_index_number_cvterm, $block_cvterm, $plot_number_cvterm, $replicate_cvterm, $plant_relationship_cvterm, $field_layout_experiment, $field_layout_cvterm, $inherits_plot_treatments, $treatments, $plot_relationship_cvterm, \%treatment_plots, \%treatment_experiments, $treatment_cvterm);
2696 $layout->generate_and_cache_layout();
2699 eval {
2700 $self->bcs_schema()->txn_do($create_plant_entities_txn);
2702 if ($@) {
2703 print STDERR "An error occurred creating the plant entities. $@\n";
2704 return 0;
2707 print STDERR "Plant entities created.\n";
2708 return 1;
2711 =head2 function save_plant_entries()
2713 Usage: $trial->save_plant_entries(\%data, $plants_per_plot, $inherits_plot_treatments);
2714 Desc: Some trials require plant-level data. It is possible to upload
2715 plant_names to save.
2716 Ret:
2717 Args: Requires $plants_per_plot and \%data which is a hashref of the data parsed from the
2718 uploaded file.
2719 example: { 'myplotname1' => { 'plot_stock_id'=>123, 'plant_names'=>['plot1_plant1', 'plot1_plant2'] }, ... }
2720 Side Effects:
2721 Example:
2723 =cut
2725 sub save_plant_entries {
2726 my $self = shift;
2727 my $parsed_data = shift;
2728 my $plants_per_plot = shift;
2729 my $inherits_plot_treatments = shift;
2731 my $create_plant_entities_txn = sub {
2732 my $chado_schema = $self->bcs_schema();
2733 my $layout = CXGN::Trial::TrialLayout->new( { schema => $chado_schema, trial_id => $self->get_trial_id(), experiment_type=>'field_layout' });
2734 my $design = $layout->get_design();
2736 my $accession_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'accession', 'stock_type')->cvterm_id();
2737 my $cross_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'cross', 'stock_type')->cvterm_id();
2738 my $family_name_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'family_name', 'stock_type')->cvterm_id();
2739 my $plant_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant', 'stock_type')->cvterm_id();
2740 my $plot_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot', 'stock_type')->cvterm_id();
2741 my $plot_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot_of', 'stock_relationship')->cvterm_id();
2742 my $plant_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_of', 'stock_relationship')->cvterm_id();
2743 my $plant_index_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_index_number', 'stock_property')->cvterm_id();
2744 my $block_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'block', 'stock_property')->cvterm_id();
2745 my $plot_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot number', 'stock_property')->cvterm_id();
2746 my $replicate_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'replicate', 'stock_property')->cvterm_id();
2747 my $has_plants_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_plant_entries', 'project_property')->cvterm_id();
2748 my $field_layout_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'field_layout', 'experiment_type')->cvterm_id();
2749 my $treatment_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'treatment_experiment', 'experiment_type')->cvterm_id();
2750 #my $plants_per_plot_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plants_per_plot', 'project_property')->cvterm_id();
2752 my $treatments;
2753 my %treatment_experiments;
2754 my %treatment_plots;
2755 if ($inherits_plot_treatments){
2756 $treatments = $self->get_treatments();
2757 foreach (@$treatments){
2759 my $rs = $chado_schema->resultset("Project::Projectprop")->find_or_create({
2760 type_id => $has_plants_cvterm,
2761 value => $plants_per_plot,
2762 project_id => $_->[0],
2765 my $treatment_nd_experiment = $chado_schema->resultset("Project::Project")->search( { 'me.project_id' => $_->[0] }, {select=>['nd_experiment.nd_experiment_id']})->search_related('nd_experiment_projects')->search_related('nd_experiment', { type_id => $treatment_cvterm })->single();
2766 $treatment_experiments{$_->[0]} = $treatment_nd_experiment->nd_experiment_id();
2768 my $treatment_trial = CXGN::Trial->new({ bcs_schema => $chado_schema, trial_id => $_->[0]});
2769 my $plots = $treatment_trial->get_plots();
2770 foreach my $plot (@$plots){
2771 $treatment_plots{$_->[0]}->{$plot->[0]} = 1;
2776 my $rs = $chado_schema->resultset("Project::Projectprop")->find_or_create({
2777 type_id => $has_plants_cvterm,
2778 value => $plants_per_plot,
2779 project_id => $self->get_trial_id(),
2783 my $field_layout_experiment = $chado_schema->resultset("Project::Project")->search( { 'me.project_id' => $self->get_trial_id() }, {select=>['nd_experiment.nd_experiment_id']})->search_related('nd_experiment_projects')->search_related('nd_experiment', { type_id => $field_layout_cvterm })->single();
2785 while( my ($key, $val) = each %$parsed_data){
2786 my $plot_stock_id = $key;
2787 my $plot_name = $val->{plot_name};
2788 print STDERR " ... creating plants for plot $plot_name...\n";
2789 my $plot_row = $chado_schema->resultset("Stock::Stock")->find( { stock_id=>$plot_stock_id });
2791 if (!$plot_row) {
2792 print STDERR "The plot $plot_name is not found in the database\n";
2793 return "The plot $plot_name is not yet in the database. Cannot create plant entries.";
2796 my $parent_plot = $plot_row->stock_id();
2797 my $parent_plot_name = $plot_row->uniquename();
2798 my $parent_plot_organism = $plot_row->organism_id();
2800 my $plant_index_number = 1;
2801 my $plant_names = $val->{plant_names};
2802 my $plant_index_numbers = $val->{plant_index_numbers};
2803 my $increment = 0;
2804 foreach my $plant_name (@$plant_names) {
2805 my $given_plant_index_number = $plant_index_numbers->[$increment];
2806 my $plant_index_number_save = $given_plant_index_number ? $given_plant_index_number : $plant_index_number;
2808 $self->_save_plant_entry($chado_schema, $accession_cvterm, $cross_cvterm, $family_name_cvterm, $parent_plot_organism, $parent_plot_name, $parent_plot, $plant_name, $plant_cvterm, $plant_index_number_save, $plant_index_number_cvterm, $block_cvterm, $plot_number_cvterm, $replicate_cvterm, $plant_relationship_cvterm, $field_layout_experiment, $field_layout_cvterm, $inherits_plot_treatments, $treatments, $plot_relationship_cvterm, \%treatment_plots, \%treatment_experiments, $treatment_cvterm);
2809 $plant_index_number++;
2810 $increment++;
2814 $layout->generate_and_cache_layout();
2817 eval {
2818 $self->bcs_schema()->txn_do($create_plant_entities_txn);
2820 if ($@) {
2821 print STDERR "An error occurred creating the plant entities. $@\n";
2822 return 0;
2825 print STDERR "Plant entities created.\n";
2826 return 1;
2829 sub _save_plant_entry {
2830 my $self = shift;
2831 my $chado_schema = shift;
2832 my $accession_cvterm = shift;
2833 my $cross_cvterm = shift;
2834 my $family_name_cvterm = shift;
2835 my $parent_plot_organism = shift;
2836 my $parent_plot_name = shift;
2837 my $parent_plot = shift;
2838 my $plant_name = shift;
2839 my $plant_cvterm = shift;
2840 my $plant_index_number = shift;
2841 my $plant_index_number_cvterm = shift;
2842 my $block_cvterm = shift;
2843 my $plot_number_cvterm = shift;
2844 my $replicate_cvterm = shift;
2845 my $plant_relationship_cvterm = shift;
2846 my $field_layout_experiment = shift;
2847 my $field_layout_cvterm = shift;
2848 my $inherits_plot_treatments = shift;
2849 my $treatments = shift;
2850 my $plot_relationship_cvterm = shift;
2851 my $treatment_plots_ref = shift;
2852 my $treatment_experiments_ref = shift;
2853 my $treatment_cvterm = shift;
2854 my %treatment_plots = %$treatment_plots_ref;
2855 my %treatment_experiments = %$treatment_experiments_ref;
2857 my $plant = $chado_schema->resultset("Stock::Stock")->create({
2858 organism_id => $parent_plot_organism,
2859 name => $plant_name,
2860 uniquename => $plant_name,
2861 type_id => $plant_cvterm,
2864 my $plantprop = $chado_schema->resultset("Stock::Stockprop")->create( {
2865 stock_id => $plant->stock_id(),
2866 type_id => $plant_index_number_cvterm,
2867 value => $plant_index_number,
2870 #The plant inherits the properties of the plot.
2871 my $plot_props = $chado_schema->resultset("Stock::Stockprop")->search({ stock_id => $parent_plot, type_id => [$block_cvterm, $plot_number_cvterm, $replicate_cvterm] });
2872 while (my $prop = $plot_props->next() ) {
2873 #print STDERR $plant->uniquename()." ".$prop->type_id()."\n";
2874 $plantprop = $chado_schema->resultset("Stock::Stockprop")->create( {
2875 stock_id => $plant->stock_id(),
2876 type_id => $prop->type_id(),
2877 value => $prop->value(),
2881 #the plant has a relationship to the plot
2882 my $stock_relationship = $self->bcs_schema()->resultset("Stock::StockRelationship")->create({
2883 subject_id => $parent_plot,
2884 object_id => $plant->stock_id(),
2885 type_id => $plant_relationship_cvterm,
2888 #the plant has a relationship to the accession
2889 my $plot_accession_rs = $self->bcs_schema()->resultset("Stock::StockRelationship")->search({'me.subject_id'=>$parent_plot, 'me.type_id'=>$plot_relationship_cvterm, 'object.type_id'=>[$accession_cvterm, $cross_cvterm, $family_name_cvterm] }, {'join'=>'object'});
2890 if ($plot_accession_rs->count != 1){
2891 die "There is not 1 stock_relationship of type plot_of between the plot $parent_plot and an accession, a cross or a family_name.";
2893 $stock_relationship = $self->bcs_schema()->resultset("Stock::StockRelationship")->create({
2894 subject_id => $plant->stock_id(),
2895 object_id => $plot_accession_rs->first->object_id,
2896 type_id => $plant_relationship_cvterm,
2899 #link plant to project through nd_experiment. also add nd_genolocation_id of plot to nd_experiment for the plant
2900 my $plant_nd_experiment_stock = $chado_schema->resultset("NaturalDiversity::NdExperimentStock")->create({
2901 nd_experiment_id => $field_layout_experiment->nd_experiment_id(),
2902 type_id => $field_layout_cvterm,
2903 stock_id => $plant->stock_id(),
2906 if ($inherits_plot_treatments){
2907 if($treatments){
2908 foreach (@$treatments){
2909 my $plots = $treatment_plots{$_->[0]};
2910 if (exists($plots->{$parent_plot})){
2911 my $plant_nd_experiment_stock = $chado_schema->resultset("NaturalDiversity::NdExperimentStock")->create({
2912 nd_experiment_id => $treatment_experiments{$_->[0]},
2913 type_id => $treatment_cvterm,
2914 stock_id => $plant->stock_id(),
2922 =head2 function has_plant_entries()
2924 Usage: $trial->has_plant_entries();
2925 Desc: Some trials require plant-level data. This function will determine if a trial has plants associated with it.
2926 Ret: Returns 1 if trial has plants, 0 if the trial does not.
2927 Args:
2928 Side Effects:
2929 Example:
2931 =cut
2933 sub has_plant_entries {
2934 my $self = shift;
2935 my $chado_schema = $self->bcs_schema();
2936 my $has_plants_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_plant_entries', 'project_property' );
2938 my $rs = $chado_schema->resultset("Project::Projectprop")->find({
2939 type_id => $has_plants_cvterm->cvterm_id(),
2940 project_id => $self->get_trial_id(),
2943 if ($rs) {
2944 return 1;
2945 } else {
2946 return 0;
2951 =head2 function create_tissue_samples()
2953 Usage: $trial->create_tissue_samples(\@tissue_names, $inherits_plot_treatments);
2954 Desc: Some trials require tissue_sample-level data. This function will
2955 add an additional layer of tissue samples for each plant.
2956 Ret:
2957 Args: an arrayref of tissue names to add to sample name e.g. ['leaf','root']
2958 Side Effects:
2959 Example:
2961 =cut
2963 sub create_tissue_samples {
2964 my $self = shift;
2965 my $tissue_names = shift;
2966 my $inherits_plot_treatments = shift;
2968 my $create_tissue_sample_entries_txn = sub {
2969 my $chado_schema = $self->bcs_schema();
2970 my $layout = CXGN::Trial::TrialLayout->new( { schema => $chado_schema, trial_id => $self->get_trial_id(), experiment_type=>'field_layout' });
2971 my $design = $layout->get_design();
2973 my $accession_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'accession', 'stock_type')->cvterm_id();
2974 my $cross_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'cross', 'stock_type')->cvterm_id();
2975 my $family_name_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'family_name', 'stock_type')->cvterm_id();
2976 my $plant_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant', 'stock_type')->cvterm_id();
2977 my $subplot_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'subplot', 'stock_type')->cvterm_id();
2978 my $plot_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot', 'stock_type')->cvterm_id();
2979 my $tissue_sample_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'tissue_sample', 'stock_type')->cvterm_id();
2980 my $plot_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot_of', 'stock_relationship')->cvterm_id();
2981 my $plant_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_of', 'stock_relationship')->cvterm_id();
2982 my $tissue_relationship_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'tissue_sample_of', 'stock_relationship')->cvterm_id();
2983 my $plant_index_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_index_number', 'stock_property')->cvterm_id();
2984 my $tissue_index_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'tissue_sample_index_number', 'stock_property')->cvterm_id();
2985 my $has_tissues_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_tissue_sample_entries', 'project_property')->cvterm_id();
2986 my $block_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'block', 'stock_property')->cvterm_id();
2987 my $plot_number_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot number', 'stock_property')->cvterm_id();
2988 my $replicate_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'replicate', 'stock_property')->cvterm_id();
2989 my $field_layout_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'field_layout', 'experiment_type')->cvterm_id();
2990 my $treatment_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'treatment_experiment', 'experiment_type')->cvterm_id();
2992 my $treatments;
2993 my %treatment_experiments;
2994 my %treatment_plots;
2995 my %treatment_subplots;
2996 if ($inherits_plot_treatments){
2997 $treatments = $self->get_treatments();
2998 foreach (@$treatments){
3000 my $rs = $chado_schema->resultset("Project::Projectprop")->find_or_create({
3001 type_id => $has_tissues_cvterm,
3002 value => scalar(@$tissue_names),
3003 project_id => $_->[0],
3006 my $treatment_nd_experiment = $chado_schema->resultset("Project::Project")->search( { 'me.project_id' => $_->[0] }, {select=>['nd_experiment.nd_experiment_id']})->search_related('nd_experiment_projects')->search_related('nd_experiment', { type_id => $treatment_cvterm })->single();
3007 $treatment_experiments{$_->[0]} = $treatment_nd_experiment->nd_experiment_id();
3009 my $treatment_trial = CXGN::Trial->new({ bcs_schema => $chado_schema, trial_id => $_->[0]});
3010 my $plots = $treatment_trial->get_plots();
3011 foreach my $plot (@$plots){
3012 $treatment_plots{$_->[0]}->{$plot->[0]} = 1;
3014 my $subplots = $treatment_trial->get_subplots();
3015 foreach my $subplot (@$subplots){
3016 $treatment_subplots{$_->[0]}->{$subplot->[0]} = 1;
3021 my $rs = $chado_schema->resultset("Project::Projectprop")->find_or_create({
3022 type_id => $has_tissues_cvterm,
3023 value => scalar(@$tissue_names),
3024 project_id => $self->get_trial_id(),
3027 my $field_layout_experiment = $chado_schema->resultset("Project::Project")->search( { 'me.project_id' => $self->get_trial_id() }, {select=>['nd_experiment.nd_experiment_id']})->search_related('nd_experiment_projects')->search_related('nd_experiment', { type_id => $field_layout_cvterm })->single();
3029 foreach my $plot (keys %$design) {
3030 my $plant_names = $design->{$plot}->{plant_names};
3031 my $subplot_names = $design->{$plot}->{subplot_names};
3032 my $subplots_plant_names = $design->{$plot}->{subplots_plant_names};
3033 my %plant_tissue_hash;
3034 foreach my $plant_name (@$plant_names){
3035 my $parent_plot_id = $design->{$plot}->{plot_id};
3036 my $parent_plot_name = $design->{$plot}->{plot_name};
3037 my $plant_row = $chado_schema->resultset("Stock::Stock")->find( { uniquename => $plant_name, type_id=>$plant_cvterm });
3039 if (! $plant_row) {
3040 print STDERR "The plant $plant_name is not found in the database\n";
3041 return "The plant $plant_name is not yet in the database. Cannot create tissue entries.";
3044 my $parent_plant = $plant_row->stock_id();
3045 my $parent_plant_name = $plant_row->uniquename();
3046 my $parent_plant_organism = $plant_row->organism_id();
3048 my $tissue_index_number = 1;
3049 foreach my $tissue_name (@$tissue_names){
3050 my $tissue_name = $parent_plant_name."_".$tissue_name.$tissue_index_number;
3051 print STDERR "... ... creating tissue $tissue_name...\n";
3053 my $tissue = $chado_schema->resultset("Stock::Stock")->create({
3054 organism_id => $parent_plant_organism,
3055 name => $tissue_name,
3056 uniquename => $tissue_name,
3057 type_id => $tissue_sample_cvterm,
3060 my $tissueprop = $chado_schema->resultset("Stock::Stockprop")->create( {
3061 stock_id => $tissue->stock_id(),
3062 type_id => $tissue_index_number_cvterm,
3063 value => $tissue_index_number,
3065 $tissue_index_number++;
3067 #the tissue has a relationship to the plant
3068 my $stock_relationship = $self->bcs_schema()->resultset("Stock::StockRelationship")->create({
3069 object_id => $parent_plant,
3070 subject_id => $tissue->stock_id(),
3071 type_id => $tissue_relationship_cvterm,
3074 #the tissue has a relationship to the plot
3075 $stock_relationship = $self->bcs_schema()->resultset("Stock::StockRelationship")->create({
3076 object_id => $parent_plot_id,
3077 subject_id => $tissue->stock_id(),
3078 type_id => $tissue_relationship_cvterm,
3081 #the tissue has a relationship to the accession
3082 my $plant_accession_rs = $self->bcs_schema()->resultset("Stock::StockRelationship")->search({'me.subject_id'=>$parent_plant, 'me.type_id'=>$plant_relationship_cvterm, 'object.type_id'=>[$accession_cvterm, $cross_cvterm, $family_name_cvterm]}, {'join'=>'object'});
3083 if ($plant_accession_rs->count != 1){
3084 die "There is not 1 stock_relationship of type plant_of between the plant $parent_plant and an accession, a cross or a family_name.";
3086 $stock_relationship = $self->bcs_schema()->resultset("Stock::StockRelationship")->create({
3087 object_id => $plant_accession_rs->first->object_id,
3088 subject_id => $tissue->stock_id(),
3089 type_id => $tissue_relationship_cvterm,
3092 #link tissue to project through nd_experiment.
3093 my $plant_nd_experiment_stock = $chado_schema->resultset("NaturalDiversity::NdExperimentStock")->create({
3094 nd_experiment_id => $field_layout_experiment->nd_experiment_id(),
3095 type_id => $field_layout_cvterm,
3096 stock_id => $tissue->stock_id(),
3099 if ($inherits_plot_treatments){
3100 if($treatments){
3101 foreach (@$treatments){
3102 my $plots = $treatment_plots{$_->[0]};
3103 if (exists($plots->{$parent_plot_id})){
3104 my $plant_nd_experiment_stock = $chado_schema->resultset("NaturalDiversity::NdExperimentStock")->create({
3105 nd_experiment_id => $treatment_experiments{$_->[0]},
3106 type_id => $treatment_cvterm,
3107 stock_id => $tissue->stock_id(),
3114 push @{$plant_tissue_hash{$plant_name}}, $tissue->stock_id;
3119 foreach my $subplot_name (%$subplots_plant_names){
3120 my $subplot_row = $chado_schema->resultset("Stock::Stock")->find({ uniquename => $subplot_name, type_id=>$subplot_cvterm });
3121 foreach my $plant (@{$subplots_plant_names->{$subplot_name}}){
3122 foreach my $t (@{$plant_tissue_hash{$plant}}){
3123 #the tissue has a relationship to the subplot
3124 my $stock_relationship = $self->bcs_schema()->resultset("Stock::StockRelationship")->create({
3125 object_id => $subplot_row->stock_id(),
3126 subject_id => $t,
3127 type_id => $tissue_relationship_cvterm,
3130 if ($inherits_plot_treatments){
3131 if($treatments){
3132 foreach (@$treatments){
3133 my $subplots = $treatment_subplots{$_->[0]};
3134 if (exists($subplots->{$subplot_row->stock_id})){
3135 my $plant_nd_experiment_stock = $chado_schema->resultset("NaturalDiversity::NdExperimentStock")->create({
3136 nd_experiment_id => $treatment_experiments{$_->[0]},
3137 type_id => $treatment_cvterm,
3138 stock_id => $t,
3149 $layout->generate_and_cache_layout();
3152 eval {
3153 $self->bcs_schema()->txn_do($create_tissue_sample_entries_txn);
3155 if ($@) {
3156 print STDERR "An error occurred creating the tissue sample entities. $@\n";
3157 return 0;
3160 print STDERR "Tissue sample entities created.\n";
3161 return 1;
3164 =head2 function has_col_and_row_numbers()
3166 Usage: $trial->has_col_and_row_numbers();
3167 Desc: Some trials require tissue_samples from plants. This function will determine if a trial has row and column numbers for fieldMap spreadsheet download.
3168 Ret: Returns 1 if trial has row and column numbers, 0 if the trial does not.
3169 Args:
3170 Side Effects:
3171 Example:
3173 =cut
3175 sub has_col_and_row_numbers {
3176 my $self = shift;
3177 my $chado_schema = $self->bcs_schema();
3178 my $design;
3179 try {
3180 my $layout = CXGN::Trial::TrialLayout->new( { schema => $chado_schema, trial_id => $self->get_trial_id(), experiment_type=>'field_layout' });
3181 $design = $layout->get_design();
3184 my (@row_numbers, @col_numbers);
3185 foreach my $plot (keys %$design) {
3186 my $row_number = $design->{$plot}->{row_number};
3187 my $col_number = $design->{$plot}->{col_number};
3188 if ($row_number){
3189 push @row_numbers, $row_number;
3191 if ($col_number){
3192 push @col_numbers, $col_number;
3196 if (scalar(@row_numbers) ne '0' && scalar(@col_numbers) ne '0'){
3197 return 1;
3198 } else {
3199 return 0;
3204 =head2 function has_tissue_sample_entries()
3206 Usage: $trial->has_tissue_sample_entries();
3207 Desc: Some trials require tissue_samples from plants. This function will determine if a trial has tissue_samples associated with it.
3208 Ret: Returns 1 if trial has tissue_samples, 0 if the trial does not.
3209 Args:
3210 Side Effects:
3211 Example:
3213 =cut
3215 sub has_tissue_sample_entries {
3216 my $self = shift;
3217 my $chado_schema = $self->bcs_schema();
3218 my $has_tissues_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_tissue_sample_entries', 'project_property' );
3220 my $rs = $chado_schema->resultset("Project::Projectprop")->find({
3221 type_id => $has_tissues_cvterm->cvterm_id(),
3222 project_id => $self->get_trial_id(),
3225 if ($rs) {
3226 return 1;
3227 } else {
3228 return 0;
3234 =head2 function has_subplot_entries()
3236 Usage: $trial->has_subplot_entries();
3237 Desc: Some trials require subplot-level data (splitplot designs). This function will determine if a trial has subplots associated with it.
3238 Ret: Returns 1 if trial has subplots, 0 if the trial does not.
3239 Args:
3240 Side Effects:
3241 Example:
3243 =cut
3245 sub has_subplot_entries {
3246 my $self = shift;
3247 my $chado_schema = $self->bcs_schema();
3248 my $has_subplots_cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_subplot_entries', 'project_property' );
3250 my $rs = $chado_schema->resultset("Project::Projectprop")->find({
3251 type_id => $has_subplots_cvterm->cvterm_id(),
3252 project_id => $self->get_trial_id(),
3255 if ($rs) {
3256 return 1;
3257 } else {
3258 return 0;
3263 sub get_planting_date_cvterm_id {
3264 my $self = shift;
3265 my $planting_date = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project_planting_date', 'project_property');
3267 return $planting_date->cvterm_id();
3271 =head2 accessors set_design_type(), get_design_type()
3273 Usage: $trial->set_design_type("RCBD");
3274 Desc:
3275 Ret:
3276 Args:
3277 Side Effects:
3278 Example:
3280 =cut
3282 sub get_design_type {
3283 my $self = shift;
3284 my $design_prop;
3285 my $design_type;
3287 my $project = $self->bcs_schema->resultset("Project::Project")->find( { project_id => $self->get_trial_id() });
3289 $design_prop = $project->projectprops->find(
3290 { 'type.name' => 'design' },
3291 { join => 'type'}
3292 ); #there should be only one design prop.
3293 if (!$design_prop) {
3294 return;
3296 $design_type = $design_prop->value;
3297 if (!$design_type) {
3298 return;
3300 return $design_type;
3305 sub duplicate {
3308 =head2 get_accessions
3310 Usage: my $accessions = $t->get_accessions();
3311 Desc: retrieves the accessions or family names or cross unique ids used in this trial.
3312 Ret: an arrayref of { accession_name => acc_name, stock_id => stock_id, stock_type => stock_type }
3313 Args: none
3314 Side Effects:
3315 Example:
3317 =cut
3319 sub get_accessions {
3320 my $self = shift;
3321 my @accessions;
3323 my $accession_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type' )->cvterm_id();
3324 my $cross_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'cross', 'stock_type' )->cvterm_id();
3325 my $family_name_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'family_name', 'stock_type' )->cvterm_id();
3326 my $field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "field_layout", "experiment_type")->cvterm_id();
3327 my $plot_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "plot_of", "stock_relationship")->cvterm_id();
3328 my $plant_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "plant_of", "stock_relationship")->cvterm_id();
3329 my $subplot_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "subplot_of", "stock_relationship")->cvterm_id();
3330 my $tissue_sample_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "tissue_sample_of", "stock_relationship")->cvterm_id();
3332 my $q = "SELECT DISTINCT(accession.stock_id), accession.uniquename, cvterm.name
3333 FROM stock as accession
3334 JOIN cvterm on (accession.type_id = cvterm.cvterm_id)
3335 JOIN stock_relationship on (accession.stock_id = stock_relationship.object_id)
3336 JOIN stock as plot on (plot.stock_id = stock_relationship.subject_id)
3337 JOIN nd_experiment_stock on (plot.stock_id=nd_experiment_stock.stock_id)
3338 JOIN nd_experiment using(nd_experiment_id)
3339 JOIN nd_experiment_project using(nd_experiment_id)
3340 JOIN project using(project_id)
3341 WHERE accession.type_id IN (?, ?, ?)
3342 AND stock_relationship.type_id IN (?, ?, ?, ?)
3343 AND project.project_id = ?
3344 ORDER BY accession.stock_id;";
3346 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
3347 $h->execute($accession_cvterm_id, $cross_cvterm_id, $family_name_cvterm_id,$plot_of_cvterm_id, $tissue_sample_of_cvterm_id, $plant_of_cvterm_id, $subplot_of_cvterm_id,$self->get_trial_id());
3348 while (my ($stock_id, $uniquename, $stock_type) = $h->fetchrow_array()) {
3349 push @accessions, {accession_name=>$uniquename, stock_id=>$stock_id, stock_type=>$stock_type};
3351 return \@accessions;
3354 =head2 get_tissue_sources
3356 Usage: my $tissue_sources = $t->get_tissue_sources();
3357 Desc: retrieves the sources for the tisue_samples in a trial. in field_layout trials this can only be plants. In genotyping_layout trials the source of a tissue_sample can be tissue_samples, plants, plots, or accessions
3358 Ret: an arrayref of { uniquename => acc_name, type=>'plant', stock_id => stock_id }
3359 Args: none
3360 Side Effects:
3361 Example:
3363 =cut
3365 sub get_tissue_sources {
3366 my $self = shift;
3367 my @tissue_samples;
3368 my $tissue_sample_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'tissue_sample', 'stock_type' )->cvterm_id();
3369 my $tissue_sample_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "tissue_sample_of", "stock_relationship")->cvterm_id();
3370 my $q = "SELECT DISTINCT(stock.stock_id), stock.uniquename, cvterm.name
3371 FROM stock
3372 JOIN cvterm on (stock.type_id = cvterm.cvterm_id)
3373 JOIN stock_relationship on (stock.stock_id = stock_relationship.object_id)
3374 JOIN stock as tissue_sample on (tissue_sample.stock_id = stock_relationship.subject_id)
3375 JOIN nd_experiment_stock on (tissue_sample.stock_id=nd_experiment_stock.stock_id)
3376 JOIN nd_experiment using(nd_experiment_id)
3377 JOIN nd_experiment_project using(nd_experiment_id)
3378 JOIN project using(project_id)
3379 WHERE tissue_sample.type_id = $tissue_sample_cvterm_id
3380 AND stock_relationship.type_id = $tissue_sample_of_cvterm_id
3381 AND project.project_id = ?
3382 GROUP BY (stock.stock_id, cvterm.name)
3383 ORDER BY (stock.stock_id);";
3385 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
3386 $h->execute($self->get_trial_id());
3387 while (my ($stock_id, $uniquename, $type) = $h->fetchrow_array()) {
3388 push @tissue_samples, {uniquename=>$uniquename, type=>$type, stock_id=>$stock_id };
3390 return \@tissue_samples;
3393 =head2 get_plants
3395 Usage: $plants = $t->get_plants();
3396 Desc: retrieves that plants that are part of the design for this trial.
3397 Ret: an array ref containing [ plant_name, plant_stock_id ]
3398 Args:
3399 Side Effects:
3400 Example:
3402 =cut
3404 sub get_plants {
3405 my $self = shift;
3406 my @plants;
3408 my $trial_layout_download = CXGN::Trial::TrialLayoutDownload->new({
3409 schema => $self->bcs_schema,
3410 trial_id => $self->get_trial_id(),
3411 data_level => 'plants',
3412 selected_columns => {"plant_name"=>1,"plant_id"=>1},
3414 my $output = $trial_layout_download->get_layout_output()->{output};
3416 if (defined $output){
3417 my $header = shift @$output;
3418 foreach (@$output) {
3419 push @plants, [$_->[1], $_->[0]];
3421 } else {
3422 @plants = @{$self->get_observation_units_direct('plant')};
3424 return \@plants;
3427 =head2 get_plants_per_accession
3429 Usage: $plants = $t->get_plants_per_accession();
3430 Desc: retrieves that plants that are part of the design for this trial grouping them by accession.
3431 Ret: a hash ref containing { $accession_stock_id1 => [ [ plant_name1, plant_stock_id1 ], [ plant_name2, plant_stock_id2 ] ], ... }
3432 Args:
3433 Side Effects:
3434 Example:
3436 =cut
3438 sub get_plants_per_accession {
3439 my $self = shift;
3440 my %return;
3442 my $plant_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'plant', 'stock_type' )->cvterm_id();
3443 my $accession_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type' )->cvterm_id();
3444 my $family_name_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'family_name', 'stock_type' )->cvterm_id();
3445 my $cross_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'cross', 'stock_type' )->cvterm_id();
3446 my @trial_stock_type_ids;
3447 push @trial_stock_type_ids, $accession_cvterm_id, $family_name_cvterm_id, $cross_cvterm_id;
3448 my $trial_plant_rs = $self->bcs_schema->resultset("Project::Project")->find({ project_id => $self->get_trial_id(), })->search_related("nd_experiment_projects")->search_related("nd_experiment")->search_related("nd_experiment_stocks")->search_related("stock", {'stock.type_id'=>$plant_cvterm_id, 'object.type_id'=>{ in => [@trial_stock_type_ids] }}, {join=>{'stock_relationship_subjects'=>'object'}, '+select'=>['stock_relationship_subjects.object_id'], '+as'=>['accession_stock_id']});
3450 my %unique_plants;
3451 while(my $rs = $trial_plant_rs->next()) {
3452 $unique_plants{$rs->uniquename} = [$rs->stock_id, $rs->get_column('accession_stock_id')];
3454 while (my ($key, $value) = each %unique_plants) {
3455 push @{$return{$value->[1]}}, [$value->[0], $key];
3457 #print STDERR Dumper \%return;
3458 return \%return;
3461 =head2 get_seedlots
3463 Usage: my $seedlots = $trial->get_seedlots();
3464 Desc: returns a list of seedlots that are defined for the trial.
3465 Ret: an array ref of elements that contain
3466 [ seedlot_name, seedlot_stock_id ]
3467 Args: none
3468 Side Effects: db access
3469 Example:
3471 =cut
3473 sub get_seedlots {
3474 my $self = shift;
3475 my @seedlots;
3477 my $seedlot_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'seedlot', 'stock_type' )->cvterm_id();
3478 my $seed_transaction_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "seed transaction", "stock_relationship")->cvterm_id();
3480 my $q = "SELECT DISTINCT(accession.stock_id), accession.uniquename
3481 FROM stock as accession
3482 JOIN stock_relationship on (accession.stock_id = stock_relationship.object_id)
3483 JOIN stock as plot on (plot.stock_id = stock_relationship.subject_id)
3484 JOIN nd_experiment_stock on (plot.stock_id=nd_experiment_stock.stock_id)
3485 JOIN nd_experiment using(nd_experiment_id)
3486 JOIN nd_experiment_project using(nd_experiment_id)
3487 JOIN project using(project_id)
3488 WHERE accession.type_id = $seedlot_cvterm_id
3489 AND stock_relationship.type_id IN ($seed_transaction_cvterm_id)
3490 AND project.project_id = ?
3491 GROUP BY accession.stock_id
3492 ORDER BY accession.stock_id;";
3494 #Removed nd_experiment.type_id IN ($field_trial_cvterm_id, $genotyping_trial_cvterm_id) AND
3496 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
3497 $h->execute($self->get_trial_id());
3498 while (my ($stock_id, $uniquename) = $h->fetchrow_array()) {
3499 push @seedlots, [$stock_id, $uniquename];
3502 return \@seedlots;
3505 =head2 get_plots
3507 Usage: my $plots = $trial->get_plots();
3508 Desc: returns a list of plots that are defined for the trial.
3509 Ret: an array ref of elements that contain
3510 [ plot_name, plot_stock_id ]
3511 Args: none
3512 Side Effects: db access
3513 Example:
3515 =cut
3517 sub get_plots {
3518 my $self = shift;
3519 my @plots;
3521 my $trial_layout_download = CXGN::Trial::TrialLayoutDownload->new({
3522 schema => $self->bcs_schema,
3523 trial_id => $self->get_trial_id(),
3524 data_level => 'plots',
3525 selected_columns => {"plot_name"=>1,"plot_id"=>1},
3527 my $output = $trial_layout_download->get_layout_output()->{output};
3529 if (defined $output){
3530 my $header = shift @$output;
3531 foreach (@$output) {
3532 push @plots, [$_->[1], $_->[0]];
3534 } else {
3535 @plots = @{$self->get_observation_units_direct('plot')};
3537 return \@plots;
3540 sub get_observation_units_direct {
3541 my $self = shift;
3542 my $stock_type = shift;
3543 # my $nd_experiment_types = shift || ['field_layout','treatment_experiment','genotyping_layout'];
3544 my $schema = $self->bcs_schema;
3545 my @obs;
3546 my $obs_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, $stock_type, "stock_type")->cvterm_id();
3547 # my @nd_experiment_type_ids;
3548 # foreach (@$nd_experiment_types) {
3549 # push @nd_experiment_type_ids, SGN::Model::Cvterm->get_cvterm_row($schema, $_, "experiment_type")->cvterm_id();
3551 my $q = "SELECT stock.uniquename, stock.stock_id FROM stock JOIN nd_experiment_stock USING(stock_id) JOIN nd_experiment_project USING(nd_experiment_id) WHERE project_id=? AND stock.type_id=? ORDER BY stock.uniquename ASC;";
3552 my $h = $schema->storage->dbh()->prepare($q);
3553 $h->execute($self->get_trial_id(), $obs_cvterm_id);
3554 while (my ($uniquename, $stock_id) = $h->fetchrow_array()) {
3555 push @obs, [$stock_id, $uniquename];
3557 return \@obs;
3560 =head2 get_plots_per_accession
3562 Usage: $plots = $t->get_plots_per_accession();
3563 Desc: retrieves that plots that are part of the design for this trial grouping them by accession.
3564 Ret: a hash ref containing { $accession_stock_id1 => [ [ plot_name1, plot_stock_id1 ], [ plot_name2, plot_stock_id2 ] ], ... }
3565 Args:
3566 Side Effects:
3567 Example:
3569 =cut
3571 sub get_plots_per_accession {
3572 my $self = shift;
3573 my %return;
3575 # note: this function also retrieves stocks of type tissue_sample (for genotyping plates).
3576 my $plot_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'plot', 'stock_type' )->cvterm_id();
3577 my $accession_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type' )->cvterm_id();
3578 my $cross_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'cross', 'stock_type' )->cvterm_id();
3579 my $family_name_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'family_name', 'stock_type' )->cvterm_id();
3580 my $tissue_sample_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'tissue_sample', 'stock_type');
3581 my $tissue_sample_cvterm_id = $tissue_sample_cvterm ? $tissue_sample_cvterm->cvterm_id() : '';
3583 my @type_ids;
3584 push @type_ids, $plot_cvterm_id if $plot_cvterm_id;
3585 push @type_ids, $tissue_sample_cvterm_id if $tissue_sample_cvterm_id;
3587 print STDERR "TYPE IDS: ".join(", ", @type_ids);
3589 my @trial_stock_type_ids;
3590 push @trial_stock_type_ids, $accession_cvterm_id, $cross_cvterm_id, $family_name_cvterm_id;
3592 my $trial_plot_rs = $self->bcs_schema->resultset("Project::Project")->find({ project_id => $self->get_trial_id(), })->search_related("nd_experiment_projects")->search_related("nd_experiment")->search_related("nd_experiment_stocks")->search_related("stock", {'stock.type_id'=> { in => [@type_ids] }, 'object.type_id'=> { in => [@trial_stock_type_ids] }}, {join=>{'stock_relationship_subjects'=>'object'}, '+select'=>['stock_relationship_subjects.object_id'], '+as'=>['accession_stock_id']});
3594 my %unique_plots;
3595 while(my $rs = $trial_plot_rs->next()) {
3596 $unique_plots{$rs->uniquename} = [$rs->stock_id, $rs->get_column('accession_stock_id')];
3598 while (my ($key, $value) = each %unique_plots) {
3599 push @{$return{$value->[1]}}, [$value->[0], $key];
3601 #print STDERR Dumper \%return;
3602 return \%return;
3605 =head2 get_subplots
3607 Usage: my $subplots = $trial->get_subplots();
3608 Desc: returns a list of subplots that are defined for the trial.
3609 Ret: an array ref of elements that contain
3610 [ subplot_name, subplot_stock_id ]
3611 Args: none
3612 Side Effects: db access
3613 Example:
3615 =cut
3617 sub get_subplots {
3618 my $self = shift;
3619 my @subplots;
3621 my $trial_layout_download = CXGN::Trial::TrialLayoutDownload->new({
3622 schema => $self->bcs_schema,
3623 trial_id => $self->get_trial_id(),
3624 data_level => 'subplots',
3625 selected_columns => {"subplot_name"=>1,"subplot_id"=>1},
3627 my $output = $trial_layout_download->get_layout_output()->{output};
3629 if (defined $output){
3630 my $header = shift @$output;
3631 foreach (@$output) {
3632 push @subplots, [$_->[1], $_->[0]];
3634 } else {
3635 @subplots = @{$self->get_observation_units_direct('subplot')};
3637 print STDERR Dumper \@subplots;
3638 return \@subplots;
3641 =head2 get_tissue_samples
3643 Usage: $tissues = $t->get_tissue_samples();
3644 Desc: retrieves the tissue samples that are linked to plants for this trial.
3645 Ret: an array ref containing [ tissue_sample_name, tissue_sample_stock_id ]
3646 Args:
3647 Side Effects:
3648 Example:
3650 =cut
3652 sub get_tissue_samples {
3653 my $self = shift;
3654 my @tissues;
3656 my $trial_layout_download = CXGN::Trial::TrialLayoutDownload->new({
3657 schema => $self->bcs_schema,
3658 trial_id => $self->get_trial_id(),
3659 data_level => 'field_trial_tissue_samples',
3660 selected_columns => {"tissue_sample_name"=>1,"tissue_sample_id"=>1},
3662 my $output = $trial_layout_download->get_layout_output()->{output};
3663 if (defined $output){
3664 my $header = shift @$output;
3665 foreach (@$output) {
3666 push @tissues, [$_->[1], $_->[0]];
3668 } else {
3669 @tissues = @{$self->get_observation_units_direct('tissue_sample')};
3671 return \@tissues;
3674 =head2 get_controls
3676 Usage: my $controls = $t->get_controls();
3677 Desc: Returns the accessions that were used as controls in the design
3678 Ret: an arrayref containing
3679 { accession_name => control_name, stock_id => control_stock_id }
3680 Args: none
3681 Side Effects:
3682 Example:
3684 =cut
3686 sub get_controls {
3687 my $self = shift;
3688 my @controls;
3690 my $accession_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type' )->cvterm_id();
3691 my $field_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "field_layout", "experiment_type")->cvterm_id();
3692 my $genotyping_trial_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "genotyping_layout", "experiment_type")->cvterm_id();
3693 my $plot_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "plot_of", "stock_relationship")->cvterm_id();
3694 my $plant_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "plant_of", "stock_relationship")->cvterm_id();
3695 my $tissue_sample_of_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "tissue_sample_of", "stock_relationship")->cvterm_id();
3696 my $control_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "is a control", 'stock_property')->cvterm_id();
3698 my $q = "SELECT DISTINCT(accession.stock_id), accession.uniquename
3699 FROM stock as accession
3700 JOIN stock_relationship on (accession.stock_id = stock_relationship.object_id)
3701 JOIN stock as plot on (plot.stock_id = stock_relationship.subject_id)
3702 JOIN stockprop as control on (plot.stock_id=control.stock_id)
3703 JOIN nd_experiment_stock on (plot.stock_id=nd_experiment_stock.stock_id)
3704 JOIN nd_experiment using(nd_experiment_id)
3705 JOIN nd_experiment_project using(nd_experiment_id)
3706 JOIN project using(project_id)
3707 WHERE accession.type_id = $accession_cvterm_id
3708 AND stock_relationship.type_id IN ($plot_of_cvterm_id, $tissue_sample_of_cvterm_id, $plant_of_cvterm_id)
3709 AND project.project_id = ?
3710 AND control.type_id = $control_type_id
3711 GROUP BY accession.stock_id
3712 ORDER BY accession.stock_id;";
3714 #removed nd_experiment.type_id IN ($field_trial_cvterm_id, $genotyping_trial_cvterm_id) AND
3716 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
3717 $h->execute($self->get_trial_id());
3718 while (my ($stock_id, $uniquename) = $h->fetchrow_array()) {
3719 push @controls, {accession_name=> $uniquename, stock_id=>$stock_id } ;
3722 return \@controls;
3725 =head2 get_controls_by_plot
3727 Usage: my $controls = $t->get_controls_by_plot(\@plot_ids);
3728 Desc: Returns the accessions that were used as controls in a trial from a list of trial plot ids. Improves on speed of get_controls by avoiding a join through nd_experiment_stock
3729 Ret: an arrayref containing
3730 { accession_name => control_name, stock_id => control_stock_id }
3731 Args: none
3732 Side Effects:
3733 Example:
3735 =cut
3737 sub get_controls_by_plot {
3738 my $self = shift;
3739 my $plot_ids = shift;
3740 my @ids = @$plot_ids;
3741 my @controls;
3743 my $accession_rs = $self->bcs_schema->resultset('Stock::Stock')->search(
3744 { 'subject.stock_id' => { 'in' => \@ids} , 'type.name' => 'is a control' },
3745 { join => { stock_relationship_objects => { subject => { stockprops => 'type' }}}, group_by => 'me.stock_id',},
3748 while(my $accession = $accession_rs->next()) {
3749 push @controls, { accession_name => $accession->uniquename, stock_id => $accession->stock_id };
3752 return \@controls;
3755 =head2 get_treatments
3757 Usage: $plants = $t->get_treatments();
3758 Desc: retrieves the treatments that are part of this trial
3759 Ret: an array ref containing from project table [ treatment_name, treatment_id ]
3760 Args:
3761 Side Effects:
3762 Example:
3764 =cut
3766 sub get_treatments {
3767 my $self = shift;
3768 my @plants;
3769 my $treatment_rel_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "trial_treatment_relationship", "project_relationship")->cvterm_id();
3771 my $treatment_rs = $self->bcs_schema->resultset("Project::ProjectRelationship")->search({type_id=>$treatment_rel_cvterm_id, object_project_id=>$self->get_trial_id()})->search_related('subject_project');
3773 my @treatments;
3774 while(my $rs = $treatment_rs->next()) {
3775 push @treatments, [$rs->project_id, $rs->name];
3777 return \@treatments;
3780 =head2 get_trial_contacts
3782 Usage: my $contacts = $t->get_trial_contacts();
3783 Desc: Returns an arrayref of hashrefs that contain all sp_person info fpr sp_person_ids saved as projectprops to this trial
3784 Ret: an arrayref containing
3785 { sp_person_id => 1, salutation => 'Mr.', first_name => 'joe', last_name => 'doe', email => 'j@d.com' }
3786 Args: none
3787 Side Effects:
3788 Example:
3790 =cut
3792 sub get_trial_contacts {
3793 my $self = shift;
3794 my @contacts;
3796 my $sp_person_id_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema,'sp_person_id','local')->cvterm_id;
3797 my $prop_rs = $self->bcs_schema->resultset('Project::Projectprop')->search(
3798 { 'project_id' => $self->get_trial_id, 'type_id'=>$sp_person_id_cvterm_id }
3801 while(my $prop = $prop_rs->next()) {
3802 my $q = "SELECT sp_person_id, username, salutation, first_name, last_name, contact_email, user_type, phone_number, organization FROM sgn_people.sp_person WHERE sp_person_id=?;";
3803 my $h = $self->bcs_schema()->storage->dbh()->prepare($q);
3804 $h->execute($prop->value);
3805 while (my ($sp_person_id, $username, $salutation, $first_name, $last_name, $email, $user_type, $phone, $organization) = $h->fetchrow_array()){
3806 push @contacts, {
3807 sp_person_id => $sp_person_id,
3808 salutation => $salutation,
3809 first_name => $first_name,
3810 last_name => $last_name,
3811 username => $username,
3812 email => $email,
3813 type => $user_type,
3814 phone_number => $phone,
3815 organization => $organization
3820 return \@contacts;
3824 =head2 function get_data_agreement()
3826 Usage: $trial->get_data_agreement();
3827 Desc: return data agreement saved for trial.
3828 Ret:
3829 Args:
3830 Side Effects:
3831 Example:
3833 =cut
3835 sub get_data_agreement {
3836 my $self = shift;
3837 my $chado_schema = $self->bcs_schema();
3838 my $cvterm = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'data_agreement', 'project_property' );
3840 my $rs = $chado_schema->resultset("Project::Projectprop")->find({
3841 type_id => $cvterm->cvterm_id(),
3842 project_id => $self->get_trial_id(),
3845 if ($rs) {
3846 return $rs->value();
3847 } else {
3848 return;
3853 =head2 suppress_plot_phenotype
3855 Usage: my $suppress_return_error = $trial->suppress_plot_phenotype($trait_id, $plot_name, $plot_pheno_value, $phenotype_id);
3856 if ($suppress_return_error) {
3857 $c->stash->{rest} = { error => $suppress_return_error };
3858 return;
3861 Desc: Suppresses plot phenotype
3862 Ret:
3863 Args:
3864 Side Effects:
3865 Example:
3867 =cut
3869 sub suppress_plot_phenotype {
3870 my $self = shift;
3871 my $trait_id = shift;
3872 my $plot_name = shift;
3873 my $phenotype_value = shift;
3874 my $phenotype_id = shift;
3875 my $username = shift;
3876 my $timestamp = shift;
3877 my $schema = $self->bcs_schema;
3878 my $trial_id = $self->get_trial_id();
3879 my $plot_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot', 'stock_type')->cvterm_id();
3880 my $phenotype_outlier_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'phenotype_outlier', 'phenotype_property')->cvterm_id();
3881 my $error;
3882 my $json_string = { value => 1, username=>$username, timestamp=>$timestamp };
3884 my $prop_rs = $self->bcs_schema->resultset('Phenotype::Phenotypeprop')->search(
3885 { 'phenotype_id' => $phenotype_id, 'type_id'=>$phenotype_outlier_type_id }
3888 if ($prop_rs->count == 0) {
3889 my $suppress_plot_pheno = $schema->resultset("Phenotype::Phenotypeprop")->create({
3890 phenotype_id => $phenotype_id,
3891 type_id => $phenotype_outlier_type_id,
3892 value => encode_json $json_string,
3895 else {
3896 $error = "This plot phenotype has already been suppressed.";
3899 return $error;
3903 =head2 delete_assayed_trait
3905 Usage: my $delete_trait_return_error = $trial->delete_assayed_trait($c->config->{basepath}, $c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, $phenotypes_ids, [] );
3906 if ($delete_trait_return_error) {
3907 $c->stash->{rest} = { error => $delete_trait_return_error };
3908 return;
3911 Desc: Delete Assayed Traits
3912 Ret:
3913 Args:
3914 Side Effects:
3915 Example:
3917 =cut
3919 sub delete_assayed_trait {
3920 my $self = shift;
3921 my $basepath = shift;
3922 my $dbhost = shift;
3923 my $dbname = shift;
3924 my $dbuser = shift;
3925 my $dbpass = shift;
3926 my $temp_file_nd_experiment_id = shift;
3927 my $pheno_ids = shift;
3928 my $trait_ids = shift;
3930 my $trial_id = $self->get_trial_id();
3931 my $schema = $self->bcs_schema;
3932 my $phenome_schema = $self->phenome_schema;
3933 my ($error, @nd_expt_ids);
3934 my $nd_experiment_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'phenotyping_experiment', 'experiment_type')->cvterm_id();
3935 my $search_params = { 'nd_experiment.type_id' => $nd_experiment_type_id, 'nd_experiment_projects.project_id' => $trial_id };
3936 if (scalar(@$trait_ids) > 0){
3937 $search_params->{'me.observable_id'} = { '-in' => $trait_ids };
3939 if (scalar(@$pheno_ids) > 0){
3940 $search_params->{'me.phenotype_id'} = { '-in' => $pheno_ids };
3942 #$schema->storage->debug(1);
3943 if (scalar(@$pheno_ids) > 0 || scalar(@$trait_ids) > 0 ){
3944 my %phenotype_ids_and_nd_experiment_ids_to_delete;
3945 my $delete_pheno_id_rs = $schema->resultset("Phenotype::Phenotype")->search(
3946 $search_params,
3948 join => { 'nd_experiment_phenotypes' => {'nd_experiment' => 'nd_experiment_projects'} },
3949 '+select' => ['nd_experiment.nd_experiment_id'],
3950 '+as' => ['nd_expt_id'],
3952 while ( my $res = $delete_pheno_id_rs->next()){
3953 push @{$phenotype_ids_and_nd_experiment_ids_to_delete{nd_experiment_ids}}, $res->get_column('nd_expt_id');
3954 push @{$phenotype_ids_and_nd_experiment_ids_to_delete{phenotype_ids}}, $res->phenotype_id;
3956 return delete_phenotype_values_and_nd_experiment_md_values($dbhost, $dbname, $dbuser, $dbpass, $temp_file_nd_experiment_id, $basepath, $schema, \%phenotype_ids_and_nd_experiment_ids_to_delete);
3958 else {
3959 $error = "List of trait or phenotype ids was not provided for deletion.";
3961 return $error;
3964 =head2 function delete_empty_crossing_experiment()
3966 Usage:
3967 Desc:
3968 Ret:
3969 Args:
3970 Side Effects:
3971 Example:
3973 =cut
3975 sub delete_empty_crossing_experiment {
3976 my $self = shift;
3978 if ($self->cross_count() > 0) {
3979 return 'Cannot delete crossing experiment with associated crosses.';
3982 eval {
3983 my $row = $self->bcs_schema->resultset("Project::Project")->find( { project_id=> $self->get_trial_id() });
3984 $row->delete();
3985 print STDERR "deleted project ".$self->get_trial_id."\n";
3987 if ($@) {
3988 print STDERR "An error occurred during deletion: $@\n";
3989 return $@;
3993 =head2 function cross_count()
3995 Usage:
3996 Desc: The number of crosses associated with this crossing experiment
3997 Ret:
3998 Args:
3999 Side Effects:
4000 Example:
4002 =cut
4004 sub cross_count {
4005 my $self = shift;
4006 my $schema = $self->bcs_schema;
4007 my $crossing_experiment_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, "cross_experiment", "experiment_type")->cvterm_id();
4009 my $q = "SELECT count(nd_experiment_project.nd_experiment_id)
4010 FROM nd_experiment_project
4011 JOIN nd_experiment on (nd_experiment_project.nd_experiment_id = nd_experiment.nd_experiment_id)
4012 WHERE nd_experiment.type_id = $crossing_experiment_type_id
4013 AND nd_experiment_project.project_id = ?";
4014 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
4015 $h->execute($self->get_trial_id());
4016 my ($count) = $h->fetchrow_array();
4017 return $count;
4022 ##__PACKAGE__->meta->make_immutable;