minor fixes
[sgn.git] / lib / CXGN / Trial / TrialLayout.pm
blob7cdb44e30a14edf87856a81cbffc058bf9d26150
1 package CXGN::Trial::TrialLayout;
3 =head1 NAME
5 CXGN::Trial::TrialLayout - Module to get layout information about a trial (i.e. a project with a "design" projectprop)
7 =head1 USAGE
9 my $trial_layout = CXGN::Trial::TrialLayout->new({schema => $schema, trial_id => $trial_id} );
12 =head1 DESCRIPTION
15 =head1 AUTHORS
17 Jeremy D. Edwards (jde22@cornell.edu)
19 =cut
22 use Moose;
23 use MooseX::FollowPBP;
24 use Moose::Util::TypeConstraints;
25 use Try::Tiny;
26 use CXGN::Stock::StockLookup;
27 use CXGN::Location::LocationLookup;
28 use Data::Dumper;
29 use SGN::Model::Cvterm;
31 has 'schema' => (
32 is => 'rw',
33 isa => 'DBIx::Class::Schema',
34 lazy_build => 1,
35 required => 1,
37 has 'trial_id' => (isa => 'Int', is => 'rw', predicate => 'has_trial_id', trigger => \&_lookup_trial_id, required => 1);
38 has 'project' => (
39 is => 'ro',
40 isa => 'Bio::Chado::Schema::Result::Project::Project',
41 reader => 'get_project',
42 writer => '_set_project',
43 predicate => 'has_project',
45 has 'design_type' => (isa => 'Str', is => 'ro', predicate => 'has_design_type', reader => 'get_design_type', writer => '_set_design_type');
46 has 'trial_year' => (isa => 'Str', is => 'ro', predicate => 'has_trial_year', reader => 'get_trial_year', writer => '_set_trial_year');
47 has 'trial_name' => (isa => 'Str', is => 'ro', predicate => 'has_trial_name', reader => 'get_trial_name', writer => '_set_trial_name');
48 has 'trial_description' => (isa => 'Str', is => 'ro', predicate => 'has_trial_description', reader => 'get_trial_description', writer => '_set_trial_description');
49 has 'trial_location' => (isa => 'Str', is => 'ro', predicate => 'has_trial_location', reader => 'get_trial_location', writer => '_set_trial_location');
50 has 'plot_dimensions' => (isa => 'ArrayRef', is => 'ro', predicate => 'has_plot_dimensions', reader => 'get_plot_dimensions', writer => '_set_plot_dimensions');
51 has 'design' => (isa => 'HashRef', is => 'ro', predicate => 'has_design', reader => 'get_design', writer => '_set_design');
52 has 'plot_names' => (isa => 'ArrayRef', is => 'ro', predicate => 'has_plot_names', reader => 'get_plot_names', writer => '_set_plot_names', default => sub { [] } );
53 has 'block_numbers' => (isa => 'ArrayRef', is => 'ro', predicate => 'has_block_numbers', reader => 'get_block_numbers', writer => '_set_block_numbers');
54 has 'replicate_numbers' => (isa => 'ArrayRef', is => 'ro', predicate => 'has_replicate_numbers', reader => 'get_replicate_numbers', writer => '_set_replicate_numbers');
55 has 'accession_names' => (isa => 'ArrayRef', is => 'ro', predicate => 'has_accession_names', reader => 'get_accession_names', writer => '_set_accession_names');
56 has 'control_names' => (isa => 'ArrayRef', is => 'ro', predicate => 'has_control_names', reader => 'get_control_names', writer => '_set_control_names');
57 has 'row_numbers' => (isa => 'ArrayRef', is => 'rw', predicate => 'has_row_numbers', reader => 'get_row_numbers', writer => '_set_row_numbers');
58 has 'col_numbers' => (isa => 'ArrayRef', is => 'rw', predicate => 'has_col_numbers', reader => 'get_col_numbers', writer => '_set_col_numbers');
61 sub _lookup_trial_id {
62 #print STDERR "Check 2.1: ".localtime()."\n";
63 my $self = shift;
64 $self->_set_project_from_id();
65 if (!$self->has_project()) {
66 print STDERR "Trial id not found\n";
67 return;
69 my $accession_names_ref;
70 my $control_names_ref;
71 my $design_type_from_project;
73 #print STDERR "Check 2.2: ".localtime()."\n";
74 if (!$self->_get_trial_year_from_project()) {return;}
76 $self->_set_trial_year($self->_get_trial_year_from_project());
77 $self->_set_trial_name($self->get_project->name());
78 $self->_set_trial_description($self->get_project->description());
79 #print STDERR "Check 2.3: ".localtime()."\n";
81 $design_type_from_project = $self->_get_design_type_from_project();
82 if (! $design_type_from_project) {
83 print STDERR "Trial has no design type... not creating layout object.\n";
84 return;
86 if (!$self->_get_location_from_field_layout_experiment()) {
87 print STDERR "Trial has not location... not creating layout object.\n";
88 return;
91 #print STDERR "Check 2.3.1: ".localtime()."\n";
92 if (!$self->_get_location_from_field_layout_experiment()) {return;}
93 $self->_set_trial_location($self->_get_location_from_field_layout_experiment());
94 #print STDERR "Check 2.3.2: ".localtime()."\n";
95 if (!$self->has_trial_location) {return;}
97 $self->_set_plot_dimensions($self->_get_plot_dimensions_from_trial());
98 #print STDERR "Check 2.3.3: ".localtime()."\n";
99 $self->_set_design_type($self->_get_design_type_from_project());
100 #print STDERR "Check 2.3.4: ".localtime()."\n";
101 $self->_set_design($self->_get_design_from_trial());
102 #print STDERR "Check 2.4: ".localtime()."\n";
103 $self->_set_plot_names($self->_get_plot_info_fields_from_trial("plot_name") || []);
104 $self->_set_block_numbers($self->_get_plot_info_fields_from_trial("block_number") || []);
105 $self->_set_replicate_numbers($self->_get_plot_info_fields_from_trial("rep_number") || []);
106 $self->_set_row_numbers($self->_get_plot_info_fields_from_trial("row_number") || [] );
107 $self->_set_col_numbers($self->_get_plot_info_fields_from_trial("col_number") || [] );
108 #$self->_set_is_a_control($self->_get_plot_info_fields_from_trial("is_a_control"));
109 ($accession_names_ref, $control_names_ref) = $self->_get_trial_accession_names_and_control_names();
110 if ($accession_names_ref) {
111 $self->_set_accession_names($accession_names_ref);
113 if ($control_names_ref) {
114 $self->_set_control_names($control_names_ref);
116 #print STDERR "Check 2.5: ".localtime()."\n";
120 sub _get_control_plot_names_from_trial {
121 my $self = shift;
122 my %design = %{$self->get_design()};
123 my @control_names;
124 foreach my $key (sort { $a <=> $b} keys %design) {
125 my %design_info = %{$design{$key}};
126 my $is_a_control;
127 $is_a_control = $design_info{"is_a_control"};
128 if ($is_a_control) {
129 push(@control_names, $design_info{"plot_name"});
132 if (! scalar(@control_names) >= 1){
133 return;
135 return \@control_names;
139 sub _get_plot_info_fields_from_trial {
140 my $self = shift;
141 my $field_name = shift;
142 my %design = %{$self->get_design()};
143 my @field_values;
144 my %unique_field_values;
145 foreach my $key (sort { $a cmp $b} keys %design) {
146 my %design_info = %{$design{$key}};
147 if (exists($design_info{$field_name})) {
148 if (! exists($unique_field_values{$design_info{$field_name}})) {
149 #print STDERR "pushing $design_info{$field_name}...\n";
150 push(@field_values, $design_info{$field_name});
152 $unique_field_values{$design_info{$field_name}} = 1;
156 if (! scalar(@field_values) >= 1){
157 return;
159 return \@field_values;
163 sub _get_design_from_trial {
164 #print STDERR "Check 2.3.4.1: ".localtime()."\n";
165 my $self = shift;
166 my $schema = $self->get_schema();
167 my $plots_ref;
168 my @plots;
169 my %design;
171 $plots_ref = $self->_get_plots();
172 if (!$plots_ref) {
173 print STDERR "_get_design_from_trial: not plots provided... returning.\n";
174 return;
176 #print STDERR "Check 2.3.4.2: ".localtime()."\n";
177 my $project = $self->get_project();
179 my $genotyping_user_id_row = $project
180 ->search_related("nd_experiment_projects")
181 ->search_related("nd_experiment")
182 ->search_related("nd_experimentprops")
183 ->find({ 'type.name' => 'genotyping_user_id' }, {join => 'type' });
185 my $genotyping_project_name_row = $project
186 ->search_related("nd_experiment_projects")
187 ->search_related("nd_experiment")
188 ->search_related("nd_experimentprops")
189 ->find({ 'type.name' => 'genotyping_project_name' }, {join => 'type' });
190 #print STDERR "Check 2.3.4.3: ".localtime()."\n";
192 my $plot_of_cv = $schema->resultset("Cv::Cvterm")->find({name => 'plot_of'});
193 my $tissue_sample_of_cv = $schema->resultset("Cv::Cvterm")->find({ name=>'tissue_sample_of' });
194 my $plant_rel_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->get_schema, 'plant_of', 'stock_relationship' );
196 @plots = @{$plots_ref};
197 foreach my $plot (@plots) {
198 #print STDERR "_get_design_from_trial. Working on plot ".$plot->uniquename()."\n";
199 my %design_info;
201 if ($genotyping_user_id_row) {
202 $design_info{genotyping_user_id} = $genotyping_user_id_row->get_column("value") || "unknown";
203 #print STDERR "RETRIEVED: genotyping_user_id: $design{genotyping_user_id}\n";
205 if ($genotyping_project_name_row) {
206 $design_info{genotyping_project_name} = $genotyping_project_name_row->get_column("value") || "unknown";
207 #print STDERR "RETRIEVED: genotyping_project_name: $design{genotyping_project_name}\n";
209 my $plot_name = $plot->uniquename;
210 my $plot_number_prop = $plot->stockprops->find( { 'type.name' => 'plot number' }, { join => 'type'} );
211 my $block_number_prop = $plot->stockprops->find( { 'type.name' => 'block' }, { join => 'type'} );
212 my $replicate_number_prop = $plot->stockprops->find( { 'type.name' => 'replicate' }, { join => 'type'} );
213 my $range_number_prop = $plot->stockprops->find( { 'type.name' => 'range' }, { join => 'type'} );
214 my $is_a_control_prop = $plot->stockprops->find( { 'type.name' => 'is a control' }, { join => 'type'} );
215 my $row_number_prop = $plot->stockprops->find( { 'type.name' => 'row_number' }, { join => 'type'} );
216 my $col_number_prop = $plot->stockprops->find( { 'type.name' => 'col_number' }, { join => 'type'} );
217 my $accession = $plot->search_related('stock_relationship_subjects')->find({ 'type_id' => { -in => [ $plot_of_cv->cvterm_id(), $tissue_sample_of_cv->cvterm_id() ] } })->object;
218 my $plants = $plot->search_related('stock_relationship_subjects', { 'me.type_id' => $plant_rel_cvterm->cvterm_id() })->search_related('object');
220 my $accession_name = $accession->uniquename;
221 my $accession_id = $accession->stock_id;
223 $design_info{"plot_name"}=$plot_name;
224 $design_info{"plot_id"}=$plot->stock_id;
226 if ($plot_number_prop) {
227 $design_info{"plot_number"}=$plot_number_prop->value();
229 else {
230 die "no plot number stockprop found for plot $plot_name";
233 if ($block_number_prop) {
234 $design_info{"block_number"}=$block_number_prop->value();
236 if ($row_number_prop) {
237 $design_info{"row_number"}=$row_number_prop->value();
239 if ($col_number_prop) {
240 $design_info{"col_number"}=$col_number_prop->value();
242 if ($replicate_number_prop) {
243 $design_info{"rep_number"}=$replicate_number_prop->value();
245 if ($range_number_prop) {
246 $design_info{"range_number"}=$replicate_number_prop->value();
248 if ($is_a_control_prop) {
249 $design_info{"is_a_control"}=$is_a_control_prop->value();
251 if ($accession_name) {
252 $design_info{"accession_name"}=$accession_name;
254 if ($accession_id) {
255 $design_info{"accession_id"}=$accession_id;
257 if ($plants) {
258 my @plant_names;
259 my @plant_ids;
260 while (my $p = $plants->next()) {
261 my $plant_name = $p->uniquename();
262 my $plant_id = $p->stock_id();
263 push @plant_names, $plant_name;
264 push @plant_ids, $plant_id;
266 $design_info{"plant_names"}=\@plant_names;
267 $design_info{"plant_ids"}=\@plant_ids;
269 $design{$plot_number_prop->value}=\%design_info;
271 #print STDERR "Check 2.3.4.4: ".localtime()."\n";
273 return \%design;
276 sub _get_field_layout_experiment_from_project {
277 my $self = shift;
278 my $project;
279 my $field_layout_experiment;
280 $project = $self->get_project();
281 if (!$project) {
282 return;
284 $field_layout_experiment = $project
285 ->search_related("nd_experiment_projects")
286 ->search_related("nd_experiment")
287 ->find({ 'type.name' => ['field_layout', 'genotyping_layout']}, {join => 'type' });
288 return $field_layout_experiment;
292 sub _get_location_from_field_layout_experiment {
293 my $self = shift;
294 my $field_layout_experiment;
295 my $location_name;
296 $field_layout_experiment = $self -> _get_field_layout_experiment_from_project();
297 if (!$field_layout_experiment) {
298 print STDERR "No field layout detected for this trial.\n";
299 return;
301 $location_name = $field_layout_experiment -> nd_geolocation -> description();
302 #print STDERR "Location: $location_name\n";
303 return $location_name;
306 sub _get_plot_dimensions_from_trial {
307 my $self = shift;
308 if (!$self->has_trial_id()) {
309 return;
311 my $project = $self->get_project();
312 if (!$project) {
313 return;
315 my $schema = $self->get_schema();
316 my $plot_width = '';
317 my $plot_width_cvterm_id = $schema->resultset("Cv::Cvterm")->find({name => 'plot_width'});
318 my $plot_width_type_id = '';
319 if ($plot_width_cvterm_id) {
320 $plot_width_type_id = $plot_width_cvterm_id->cvterm_id;
322 my $plot_width_row = $schema->resultset('Project::Projectprop')->find({project_id => $self->get_trial_id(), type_id => $plot_width_type_id});
323 if ($plot_width_row) {
324 $plot_width = $plot_width_row->value();
328 my $plot_length = '';
329 my $plot_length_cvterm_id = $schema->resultset("Cv::Cvterm")->find({name => 'plot_length'});
330 my $plot_length_type_id = '';
331 if ($plot_length_cvterm_id) {
332 $plot_length_type_id = $plot_length_cvterm_id->cvterm_id;
334 my $plot_length_row = $schema->resultset('Project::Projectprop')->find({project_id => $self->get_trial_id(), type_id => $plot_length_type_id});
335 if ($plot_length_row) {
336 $plot_length = $plot_length_row->value();
340 my $plants_per_plot = '';
341 my $plants_per_plot_cvterm_id = $schema->resultset("Cv::Cvterm")->find({name => 'plot_length'});
342 my $plants_per_plot_type_id = '';
343 if ($plants_per_plot_cvterm_id) {
344 $plants_per_plot_type_id = $plants_per_plot_cvterm_id->cvterm_id;
346 my $plants_per_plot_row = $schema->resultset('Project::Projectprop')->find({project_id => $self->get_trial_id(), type_id => $plants_per_plot_type_id});
347 if ($plants_per_plot_row) {
348 $plants_per_plot = $plants_per_plot_row->value();
351 return [$plot_length, $plot_width, $plants_per_plot];
354 sub _set_project_from_id {
355 my $self = shift;
356 my $schema = $self->get_schema();
357 my $project;
358 if (!$self->has_trial_id()) {
359 return;
361 $project = $schema->resultset('Project::Project')->find({project_id => $self->get_trial_id()});
362 if (!$project) {
363 return;
365 $self->_set_project($project);
368 sub _get_design_type_from_project {
369 my $self = shift;
370 my $design_prop;
371 my $design_type;
372 my $project;
374 if (!$self->has_trial_id()) {
375 return;
377 $project = $self->get_project();
378 if (!$project) {
379 return;
381 $design_prop = $project->projectprops->find(
382 { 'type.name' => 'design' },
383 { join => 'type'}
384 ); #there should be only one design prop.
385 if (!$design_prop) {
386 return;
388 $design_type = $design_prop->value;
389 if (!$design_type) {
390 return;
392 return $design_type;
395 sub _get_trial_year_from_project {
396 my $self = shift;
397 my $project;
398 my $year_prop;
399 my $year;
401 if (!$self->has_trial_id()) {
402 return;
404 $project = $self->get_project();
405 if (!$project) {
406 return;
408 $year_prop = $project->projectprops->find(
409 { 'type.name' => 'project year' },
410 { join => 'type'}
411 ); #there should be only one project year prop.
412 if (!$year_prop) {
413 return;
415 $year = $year_prop->value;
416 return $year;
419 sub _get_plots {
420 my $self = shift;
421 my $project;
422 my $field_layout_experiment;
423 my @plots;
424 $project = $self->get_project();
425 if (!$project) {
426 return;
428 $field_layout_experiment = $self->_get_field_layout_experiment_from_project();
429 if (!$field_layout_experiment) {
430 print STDERR "No field layout experiment found!\n";
431 return;
433 my $plot_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->get_schema(), "plot", "stock_type")->cvterm_id();
434 my $tissue_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->get_schema(), "tissue_sample", "stock_type")->cvterm_id();
435 @plots = $field_layout_experiment->nd_experiment_stocks->search_related('stock', {'stock.type_id' => [$plot_cvterm_id, $tissue_cvterm_id] });
437 #debug...
438 #print STDERR "PLOT LIST: \n";
439 #print STDERR join "\n", map { $_->name() } @plots;
441 return \@plots;
445 sub get_plant_names {
446 my $class = shift;
447 my $args = shift;
448 my @plants;
450 my $schema = $args->{bcs_schema};
451 my $plots = $args->{plot_rs};
452 my $plant_rel_cvterm = SGN::Model::Cvterm->get_cvterm_row($schema, 'plant_of', 'stock_relationship' );
453 foreach (@$plots) {
454 my $plot_id = $_->stock_id();
455 #print STDERR $plot_id;
456 my $stock_relationships =$schema->resultset("Stock::StockRelationship")->search({
457 subject_id => $plot_id,
458 #object_id => $plant->stock_id(),
459 'me.type_id' => $plant_rel_cvterm->cvterm_id(),
460 })->search_related('object');
461 if (!$stock_relationships) {
462 print STDERR "Plot ".$_->name()." does not have plants associated with it.\n";
463 return;
465 while (my $plant = $stock_relationships->next()){
466 push @plants, $plant->name();
469 #print STDERR Dumper \@plants;
470 return \@plants;
474 sub oldget_plot_names {
475 my $self = shift;
476 my $plots_ref;
477 my @plots;
478 my @plot_names;
479 my $plot;
480 $plots_ref = $self->_get_plots();
481 if (!$plots_ref) {
482 return;
484 @plots = @{$plots_ref};
485 foreach $plot (@plots) {
486 push(@plot_names,$plot->uniquename);
487 # print "plot: ".$plot->uniquename."\n";
489 if (!scalar(@plot_names) >= 1) {
490 return;
492 return \@plot_names;
495 sub get_plot_ids {
496 my $self = shift;
497 my $plots_ref;
498 my @plots;
499 my @plot_names;
500 my $plot;
501 $plots_ref = $self->_get_plots();
502 if (!$plots_ref) {
503 return;
505 @plots = @{$plots_ref};
506 foreach $plot (@plots) {
507 push(@plot_names,$plot->stock_id);
509 if (!scalar(@plot_names) >= 1) {
510 return;
512 return \@plot_names;
515 sub _get_trial_accession_names_and_control_names {
516 my $self = shift;
517 my $schema = shift;
518 $schema = $self->get_schema();
519 my $plots_ref;
520 my @plots;
521 my $plot;
522 my $plot_of_cv;
523 my $sample_of_cv;
524 my %unique_accessions;
525 my %unique_controls;
526 my @accession_names;
527 my @control_names;
528 $plots_ref = $self->_get_plots();
529 if (!$plots_ref) {
530 return;
532 @plots = @{$plots_ref};
533 $plot_of_cv = $schema->resultset("Cv::Cvterm")->find({name => 'plot_of'});
534 $sample_of_cv = $schema->resultset("Cv::Cvterm")->find({name => 'tissue_sample_of'});
535 foreach $plot (@plots) {
536 my $accession = $plot->search_related('stock_relationship_subjects')->find({ 'type_id' => [$plot_of_cv->cvterm_id(),$sample_of_cv->cvterm_id() ]})->object;
537 my $is_a_control_prop = $plot->stockprops->find( { 'type.name' => 'is a control' }, { join => 'type'} );
538 my $is_a_control;
539 if ($is_a_control_prop) {
540 $is_a_control = $is_a_control_prop->value();
542 if ($is_a_control) {
543 $unique_controls{$accession->uniquename}=$accession->stock_id;
545 else {
546 $unique_accessions{$accession->uniquename}=$accession->stock_id;
549 foreach my $accession_name (sort { lc($a) cmp lc($b)} keys %unique_accessions) {
550 push(@accession_names, {accession_name=>$accession_name, stock_id=>$unique_accessions{$accession_name} } );
551 #print STDERR "Accession: $accession_name \n";
553 if (!scalar(@accession_names) >= 1) {
554 return;
556 foreach my $control_name (sort { lc($a) cmp lc($b)} keys %unique_controls) {
557 push(@control_names, {accession_name=>$control_name, stock_id=>$unique_controls{$control_name} } );
558 #print STDERR "Control: $control_name \n";
560 return (\@accession_names, \@control_names);
564 # sub _get_genotyping_experiment_metadata {
565 # my $self = shift;
567 # my $project = $self->get_project();
568 # if (!$project) {
569 # return;
571 # my $metadata = $project
572 # ->search_related("nd_experiment_projects")
573 # ->search_related("nd_experiment")
574 # ->search_related("nd_experimentprop")
575 # ->search({ 'type.name' => ['genotyping_user_id', 'genotyping_project_name']}, {join => 'type' });
576 # return $metadata_rs;
581 #######
583 #######