Merge pull request #5163 from solgenomics/audit-error-checking
[sgn.git] / lib / CXGN / Trial / TrialDesignStore / AbstractTrial.pm
blobc901b508e4cc672447801f34b9dd4ab309cec515
2 =head1 NAME
4 CXGN::Trial::TrialDesignStore::AbstractTrial - a class to provide function in common to all subclasses of trial store objects.
6 =cut
8 package CXGN::Trial::TrialDesignStore::AbstractTrial;
10 use Moose;
11 use MooseX::FollowPBP;
12 use Try::Tiny;
13 use Data::Dumper;
14 use CXGN::Stock;
15 use JSON;
17 =head1 ACCESSORS
19 =head2 bcs_schema()
21 Bio::Chado::Schema object, required parameter.
23 =cut
25 has 'bcs_schema' => (
26 is => 'rw',
27 isa => 'DBIx::Class::Schema',
28 predicate => 'has_chado_schema',
29 required => 1,
32 =head2 set_trial_id(), get_trial_id()
34 The trial id, which essentially is a project_id. Required.
36 =cut
38 has 'trial_id' => (isa => 'Int', is => 'rw', predicate => 'has_trial_id', required => 1);
40 =head2 set_trial_name(), get_trial_name()
42 The name of the trial. Should be unique in the database.
44 =cut
46 has 'trial_name' => (isa => 'Str', is => 'rw', predicate => 'has_trial_name', required => 0);
48 =head2 set_nd_experiment_id(), get_nd_experiment_id(), has_nd_experiment_id()
50 The nd_experiment_id of the associated design data.
52 =cut
54 has 'nd_experiment_id' => (isa => 'Int', is => 'rw', predicate => 'has_nd_experiment_id', required => 0);
56 =head2 set_nd_geolocation_id(), get_nd_geolocation_id(), has_nd_geolocation_id()
58 The nd_geolocation_id of this trial (globally, not individiual plots etc). Required.
60 =cut
62 has 'nd_geolocation_id' => (isa => 'Int', is => 'rw', predicate => 'has_nd_geolocation_id', required => 1);
64 =head2 set_design_type(), get_design_type(), has_design_type()
66 The type of the design. CBSD, etc. Optional.
68 =cut
70 has 'design_type' => (isa => 'Maybe[Str]', is => 'rw', predicate => 'has_design_type', required => 0);
72 =head2 set_design(), get_design(), has_design()
74 The Perl design data structure.
76 =cut
78 has 'design' => (isa => 'HashRef[HashRef]|Undef', is => 'rw', predicate => 'has_design', required => 1);
80 =head2 set_is_genotyping(), get_is_genotyping()
82 Whether this is a genotyping experiment. (deprecated; rather, check the object type).
84 =cut
86 has 'is_genotyping' => (isa => 'Bool', is => 'rw', required => 0, default => 0);
88 =head2 set_is_analysis(), get_is_analysis()
90 Whether the object is an analysis object. Assumes is_genotyping to be false.
92 =cut
94 has 'is_analysis' => (isa => 'Bool', is => 'rw', required => 0, default => 0);
96 =head2 set_is_sampling_trial(), get_is_sampling_trial()
98 Whether the object is a sampling trial object. Assumes is_sampling_trial to be false.
100 =cut
102 has 'is_sampling_trial' => (isa => 'Bool', is => 'rw', required => 0, default => 0);
104 =head2 set_stock_exist(), get_stock_exist()
106 If the stocks in the design were checked and whether the check passed. Internal use only.
108 =cut
110 has 'stocks_exist' => (isa => 'Bool', is => 'rw', required => 0, default => 0);
112 =head2 set_new_treatment_has_plant_entries(), get_new_treatment_has_plant_entries()
114 Whether this treatment has plant entries.
116 =cut
118 has 'new_treatment_has_plant_entries' => (isa => 'Maybe[Int]', is => 'rw', required => 0, default => 0);
120 =head2 set_new_treatment_has_subplot_entries(), get_new_treatment_has_subplot_entries()
122 Whether this treatment has subplot entries.
124 =cut
126 has 'new_treatment_has_subplot_entries' => (isa => 'Maybe[Int]', is => 'rw', required => 0, default => 0);
128 =head2 set_new_treatment_has_tissue_sample_entries(), get_new_treatment_has_tissue_sample_entries()
130 Whether this treatment has tissue_sample entries.
132 =cut
134 has 'new_treatment_has_tissue_sample_entries' => (isa => 'Maybe[Int]', is => 'rw', required => 0, default => 0);
136 =head2 set_new_treatment_date, get_new_treatment_date()
138 A new treatment date.
140 =cut
142 has 'new_treatment_date' => (isa => 'Maybe[Str]', is => 'rw', required => 0, default => 0);
144 =head2 set_new_treatment_year, get_new_treatment_year()
146 A new treatment year.
148 =cut
151 has 'new_treatment_year' => (isa => 'Maybe[Str]', is => 'rw', required => 0, default => 0);
153 =head2 set_new_treatment_type, get_new_treatment_type()
155 A new treatment type.
157 =cut
159 has 'new_treatment_type' => (isa => 'Maybe[Str]', is => 'rw', required => 0, default => 0);
161 =head2 set_operator(), get_operator()
163 An name for an operator performing the action.
165 =cut
167 has 'operator' => (isa => 'Str', is => 'rw', required => 1);
169 =head2 set_owner_id(), get_owner_id()
171 An owner id
173 =cut
175 has 'owner_id' => (isa => 'Int', is => 'rw', required => 0);
177 =head2 set_source_stock_types(), get_source_stock_types()
179 The source stock types. Needs to be defined in the constructor (BUILD) of the subclass.
181 =cut
183 has 'source_stock_types' => (isa => 'ArrayRef', is => 'rw');
185 =head1 CVTERM accessors
187 =head2 set_nd_experiment_type_id(), get_nd_experiment_type_id()
189 The experiment type id for the trial category.
190 The values are:
191 xxx for field trials
192 yyy for genotyping trials
193 zzz for analyses
195 =cut
197 has 'nd_experiment_type_id' => (isa => 'Int', is => 'rw');
199 =head2 set_stock_relationship_type_id(), get_stock_relationship_type_id()
201 The stock_relationship_type_id of the elements in the design.
203 =cut
205 has 'stock_relationship_type_id' => (isa => 'Int', is => 'rw');
207 =head2 set_stock_type_id(), get_stock_type_id()
209 The stock type_id of the elements in the design.
211 =cut
213 has 'stock_type_id' => (isa => 'Int', is => 'rw');
215 =head2 set_valid_properties(), get_valid_properties()
217 The properties that are valid in the object for validation purposes. Needs to be set in the constructor of the subclass.
219 =cut
221 has 'valid_properties' => (isa => 'Maybe[ArrayRef]', is => 'rw');
223 has 'seedlot_cvterm_id' => (isa => 'Int', is => 'rw');
225 has 'accession_cvterm_id' => (isa => 'Int', is => 'rw');
227 has 'tissue_sample_cvterm_id' => (isa => 'Int', is => 'rw');
229 has 'tissue_sample_of_cvterm_id' => (isa => 'Int', is => 'rw');
231 has 'plot_cvterm_id' => (isa => 'Int', is => 'rw');
233 has 'plot_of_cvterm_id' => (isa => 'Int', is => 'rw');
235 has 'plant_cvterm_id' => (isa => 'Int', is => 'rw');
237 has 'subplot_cvterm_id' => (isa => 'Int', is => 'rw');
239 has 'subplot_of_cvterm_id' => (isa => 'Int', is => 'rw');
241 has 'plant_of_subplot_cvterm_id' => (isa => 'Int', is => 'rw');
243 has 'subplot_index_number_cvterm_id' => (isa => 'Int', is => 'rw');
245 has 'plant_of_cvterm_id' => (isa => 'Int', is => 'rw');
247 has 'plant_index_number_cvterm_id' => (isa => 'Int', is => 'rw');
249 has 'replicate_cvterm_id' => (isa => 'Int', is => 'rw');
251 has 'block_cvterm_id' => (isa => 'Int', is => 'rw');
253 has 'plot_number_cvterm_id' => (isa => 'Int', is => 'rw');
255 has 'is_control_cvterm_id' => (isa => 'Int', is => 'rw');
257 has 'range_cvterm_id' => (isa => 'Int', is => 'rw');
259 has 'row_number_cvterm_id' => (isa => 'Int', is => 'rw');
261 has 'col_number_cvterm_id' => (isa => 'Int', is => 'rw');
263 has 'is_blank_cvterm_id' => (isa => 'Int', is => 'rw');
265 has 'concentration_cvterm_id' => (isa => 'Int', is => 'rw');
267 has 'volume_cvterm_id' => (isa => 'Int', is => 'rw');
269 has 'dna_person_cvterm_id' => (isa => 'Int', is => 'rw');
271 has 'extraction_cvterm_id' => (isa => 'Int', is => 'rw');
273 has 'tissue_type_cvterm_id' => (isa => 'Int', is => 'rw');
275 has 'acquisition_date_cvterm_id' => (isa => 'Int', is => 'rw');
277 has 'ncbi_taxonomy_id_cvterm_id' => (isa => 'Int', is => 'rw');
279 has 'notes_cvterm_id' => (isa => 'Int', is => 'rw');
281 has 'treatment_nd_experiment_type_id' => (isa => 'Int', is => 'rw');
283 has 'project_design_cvterm_id' => (isa => 'Int', is => 'rw');
285 has 'management_factor_year_cvterm_id' => (isa => 'Int', is => 'rw');
287 has 'management_factor_date_cvterm_id' => (isa => 'Int', is => 'rw');
289 has 'management_factor_type_cvterm_id' => (isa => 'Int', is => 'rw');
291 has 'trial_treatment_relationship_cvterm_id' => (isa => 'Int', is => 'rw');
293 has 'has_plants_cvterm' => (isa => 'Int', is => 'rw');
295 has 'has_subplots_cvterm' => (isa => 'Int', is => 'rw');
297 has 'has_tissues_cvterm' => (isa => 'Int', is => 'rw');
299 has 'cross_cvterm_id' => (isa => 'Int', is => 'rw');
301 has 'family_name_cvterm_id' => (isa => 'Int', is => 'rw');
303 has 'facility_identifier_cvterm_id' => (isa => 'Int', is => 'rw');
305 sub BUILD {
306 my $self = shift;
307 my $chado_schema = $self->get_bcs_schema();
309 $self->set_seedlot_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'seedlot', 'stock_type')->cvterm_id());
311 $self->set_accession_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'accession', 'stock_type')->cvterm_id());
313 $self->set_tissue_sample_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'tissue_sample', 'stock_type')->cvterm_id());
315 $self->set_tissue_sample_of_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'tissue_sample_of', 'stock_relationship')->cvterm_id());
317 $self->set_plot_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot', 'stock_type')->cvterm_id());
319 $self->set_plot_of_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot_of', 'stock_relationship')->cvterm_id());
321 $self->set_plant_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant', 'stock_type')->cvterm_id());
323 $self->set_subplot_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'subplot', 'stock_type')->cvterm_id());
325 $self->set_subplot_of_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'subplot_of', 'stock_relationship')->cvterm_id());
327 $self->set_plant_of_subplot_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_of_subplot', 'stock_relationship')->cvterm_id());
329 $self->set_subplot_index_number_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'subplot_index_number', 'stock_property')->cvterm_id());
331 $self->set_plant_of_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_of', 'stock_relationship')->cvterm_id());
333 $self->set_plant_index_number_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plant_index_number', 'stock_property')->cvterm_id());
335 $self->set_replicate_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'replicate', 'stock_property')->cvterm_id());
337 $self->set_block_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'block', 'stock_property')->cvterm_id());
339 $self->set_plot_number_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'plot number', 'stock_property')->cvterm_id());
341 $self->set_is_control_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'is a control', 'stock_property')->cvterm_id());
343 $self->set_range_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'range', 'stock_property')->cvterm_id());
345 $self->set_row_number_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'row_number', 'stock_property')->cvterm_id());
347 $self->set_col_number_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'col_number', 'stock_property')->cvterm_id());
349 $self->set_is_blank_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'is_blank', 'stock_property')->cvterm_id());
351 $self->set_concentration_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'concentration', 'stock_property')->cvterm_id());
353 $self->set_volume_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'volume', 'stock_property')->cvterm_id());
355 $self->set_dna_person_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'dna_person', 'stock_property')->cvterm_id());
357 $self->set_extraction_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'extraction', 'stock_property')->cvterm_id());
359 $self->set_tissue_type_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'tissue_type', 'stock_property')->cvterm_id());
361 $self->set_acquisition_date_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'acquisition date', 'stock_property')->cvterm_id());
363 $self->set_ncbi_taxonomy_id_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'ncbi_taxonomy_id', 'stock_property')->cvterm_id());
365 $self->set_notes_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'notes', 'stock_property')->cvterm_id());
367 $self->set_treatment_nd_experiment_type_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'treatment_experiment', 'experiment_type')->cvterm_id());
369 $self->set_project_design_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'design', 'project_property')->cvterm_id());
371 $self->set_management_factor_year_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project year', 'project_property')->cvterm_id());
373 $self->set_management_factor_date_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'management_factor_date', 'project_property')->cvterm_id());
375 $self->set_management_factor_type_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'management_factor_type', 'project_property')->cvterm_id());
377 $self->set_trial_treatment_relationship_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'trial_treatment_relationship', 'project_relationship')->cvterm_id());
379 $self->set_has_plants_cvterm(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_plant_entries', 'project_property')->cvterm_id());
381 $self->set_has_subplots_cvterm(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_subplot_entries', 'project_property')->cvterm_id());
383 $self->set_has_tissues_cvterm(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'project_has_tissue_sample_entries', 'project_property')->cvterm_id());
385 $self->set_cross_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'cross', 'stock_type')->cvterm_id());
387 $self->set_family_name_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'family_name', 'stock_type')->cvterm_id());
389 $self->set_facility_identifier_cvterm_id(SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'facility_identifier', 'stock_property')->cvterm_id());
393 sub validate_design {
394 print STDERR "Implement validate_design in subclass\n";
397 sub store {
398 print STDERR "Saving design ".localtime()."\n";
399 my $self = shift;
400 my $chado_schema = $self->get_bcs_schema;
401 my $design_type = $self->get_design_type;
402 my %design = %{$self->get_design};
403 my $trial_id = $self->get_trial_id;
404 my $nd_geolocation_id = $self->get_nd_geolocation_id;
407 my $nd_experiment_type_id = $self->get_nd_experiment_type_id();
408 my $stock_type_id = $self->get_stock_type_id();
409 my $stock_rel_type_id = $self->get_stock_relationship_type_id();
410 my $additional_info_type_id = SGN::Model::Cvterm->get_cvterm_row($chado_schema, 'stock_additional_info', 'stock_property')->cvterm_id();
412 my @source_stock_types = @{$self->get_source_stock_types()};
414 print STDERR "!!!!!! stock rel type id = $stock_rel_type_id, stock type_id = $stock_type_id\n";
416 #$chado_schema->storage->debug(1);
417 my $nd_experiment_id;
418 if ($self->has_nd_experiment_id){
419 $nd_experiment_id = $self->get_nd_experiment_id();
420 } else {
421 my $nd_experiment_project;
422 my $nd_experiment_project_rs = $chado_schema->resultset('NaturalDiversity::NdExperimentProject')->search(
424 'me.project_id'=>$trial_id,
425 'nd_experiment.type_id'=>$self->get_nd_experiment_type_id,
426 'nd_experiment.nd_geolocation_id'=>$self->get_nd_geolocation_id
428 { join => 'nd_experiment'}
431 if ($nd_experiment_project_rs->count < 1) {
432 my $nd_experiment = $chado_schema->resultset('NaturalDiversity::NdExperiment')
433 ->create({
434 nd_geolocation_id => $self->get_nd_geolocation_id,
435 type_id => $nd_experiment_type_id,
437 $nd_experiment_project = $nd_experiment->find_or_create_related('nd_experiment_projects', {project_id => $self->get_trial_id} );
438 } elsif ($nd_experiment_project_rs->count > 1) {
439 print STDERR "ERROR: More than one nd_experiment of type=$nd_experiment_type_id for project=$trial_id\n";
440 $nd_experiment_project = $nd_experiment_project_rs->first;
441 } elsif ($nd_experiment_project_rs->count == 1) {
442 print STDERR "OKAY: NdExperimentProject type=$nd_experiment_type_id for project$trial_id\n";
443 $nd_experiment_project = $nd_experiment_project_rs->first;
445 if ($nd_experiment_project){
446 $nd_experiment_id = $nd_experiment_project->nd_experiment_id();
450 my %seen_accessions_hash;
451 my %seen_seedlots_hash;
452 foreach my $key (keys %design) {
453 if ($design{$key}->{stock_name}) {
454 my $stock_name = $design{$key}->{stock_name};
455 $seen_accessions_hash{$stock_name}++;
457 if ($design{$key}->{seedlot_name}) {
458 my $stock_name = $design{$key}->{seedlot_name};
459 $seen_seedlots_hash{$stock_name}++;
462 my @seen_accessions = keys %seen_accessions_hash;
463 my @seen_seedlots = keys %seen_seedlots_hash;
465 my $seedlot_rs = $chado_schema->resultset('Stock::Stock')->search({
466 'is_obsolete' => { '!=' => 't' },
467 'type_id' => $self->get_seedlot_cvterm_id,
468 'uniquename' => {-in=>\@seen_seedlots}
470 my %seedlot_data;
471 while (my $s = $seedlot_rs->next()) {
472 $seedlot_data{$s->uniquename} = $s->stock_id;
475 my $rs = $chado_schema->resultset('Stock::Stock')->search({
476 'is_obsolete' => { '!=' => 't' },
477 'type_id' => {-in=>\@source_stock_types},
478 'uniquename' => {-in=>\@seen_accessions}
480 my %stock_data;
481 while (my $s = $rs->next()) {
482 $stock_data{$s->uniquename} = [$s->stock_id, $s->organism_id, $s->type_id];
485 my $stock_id_checked;
486 my $stock_name_checked;
487 my $organism_id_checked;
488 my $stock_type_checked;
489 my $timestamp = localtime();
491 my $coderef = sub {
493 #print STDERR Dumper \%design;
494 my %new_stock_ids_hash;
495 my $stock_rs = $chado_schema->resultset("Stock::Stock");
497 foreach my $key (keys %design) {
499 if ($key eq 'treatments'){
500 next;
503 my $plot_name;
504 if ($design{$key}->{plot_name}) {
505 $plot_name = $design{$key}->{plot_name};
507 my $plot_number;
508 if ($design{$key}->{plot_number}) {
509 $plot_number = $design{$key}->{plot_number};
510 } else {
511 $plot_number = $key;
513 my $plant_names;
514 if ($design{$key}->{plant_names}) {
515 $plant_names = $design{$key}->{plant_names};
517 my $subplot_names;
518 if ($design{$key}->{subplots_names}) {
519 $subplot_names = $design{$key}->{subplots_names};
521 my $subplots_plant_names;
522 if ($design{$key}->{subplots_plant_names}) {
523 $subplots_plant_names = $design{$key}->{subplots_plant_names};
525 my $stock_name;
526 if ($design{$key}->{stock_name}) {
527 $stock_name = $design{$key}->{stock_name};
529 my $seedlot_name;
530 my $seedlot_stock_id;
531 if ($design{$key}->{seedlot_name}) {
532 $seedlot_name = $design{$key}->{seedlot_name};
533 $seedlot_stock_id = $seedlot_data{$seedlot_name};
535 my $num_seed_per_plot;
536 if($design{$key}->{num_seed_per_plot}){
537 $num_seed_per_plot = $design{$key}->{num_seed_per_plot};
539 my $weight_gram_seed_per_plot;
540 if($design{$key}->{weight_gram_seed_per_plot}){
541 $weight_gram_seed_per_plot = $design{$key}->{weight_gram_seed_per_plot};
543 my $block_number;
544 if ($design{$key}->{block_number}) { #set block number to 1 if no blocks are specified
545 $block_number = $design{$key}->{block_number};
546 } else {
547 $block_number = 1;
549 my $rep_number;
550 if ($design{$key}->{rep_number}) { #set rep number to 1 if no reps are specified
551 $rep_number = $design{$key}->{rep_number};
552 } else {
553 $rep_number = 1;
555 my $is_a_control;
556 if ($design{$key}->{is_a_control}) {
557 $is_a_control = $design{$key}->{is_a_control};
559 my $row_number;
560 if ($design{$key}->{row_number}) {
561 $row_number = $design{$key}->{row_number};
563 my $col_number;
564 if ($design{$key}->{col_number}) {
565 $col_number = $design{$key}->{col_number};
567 my $range_number;
568 if ($design{$key}->{range_number}) {
569 $range_number = $design{$key}->{range_number};
571 my $well_is_blank;
572 if ($design{$key}->{is_blank}) {
573 $well_is_blank = $design{$key}->{is_blank};
575 my $well_concentration;
576 if ($design{$key}->{concentration}) {
577 $well_concentration = $design{$key}->{concentration};
579 my $well_volume;
580 if ($design{$key}->{volume}) {
581 $well_volume = $design{$key}->{volume};
583 my $well_dna_person;
584 if ($design{$key}->{dna_person}) {
585 $well_dna_person = $design{$key}->{dna_person};
587 my $well_extraction;
588 if ($design{$key}->{extraction}) {
589 $well_extraction = $design{$key}->{extraction};
591 my $well_tissue_type;
592 if ($design{$key}->{tissue_type}) {
593 $well_tissue_type = $design{$key}->{tissue_type};
595 my $acquisition_date;
596 if ($design{$key}->{acquisition_date}) {
597 $acquisition_date = $design{$key}->{acquisition_date};
599 my $notes;
600 if ($design{$key}->{notes}) {
601 $notes = $design{$key}->{notes};
603 my $ncbi_taxonomy_id;
604 if ($design{$key}->{ncbi_taxonomy_id}) {
605 $ncbi_taxonomy_id = $design{$key}->{ncbi_taxonomy_id};
607 my $additional_info = $design{$key}->{additional_info} ? encode_json $design{$key}->{additional_info} : undef;
609 my $facility_identifier;
610 if ($design{$key}->{facility_identifier}) {
611 $facility_identifier = $design{$key}->{facility_identifier};
614 #check if stock_name exists in database by checking if stock_name is key in %stock_data. if it is not, then check if it exists as a synonym in the database.
615 if ($stock_data{$stock_name}) {
616 $stock_id_checked = $stock_data{$stock_name}[0];
617 $organism_id_checked = $stock_data{$stock_name}[1];
618 $stock_type_checked = $stock_data{$stock_name}[2];
619 $stock_name_checked = $stock_name;
620 } else {
621 my $parent_stock;
622 my $stock_lookup = CXGN::Stock::StockLookup->new(schema => $chado_schema);
623 $stock_lookup->set_stock_name($stock_name);
624 $parent_stock = $stock_lookup->get_stock($self->get_accession_cvterm_id());
625 if (!$parent_stock) {
626 die ("Error while saving trial layout: no accession found matching $stock_name");
629 $stock_id_checked = $parent_stock->stock_id();
630 $stock_name_checked = $parent_stock->uniquename;
631 $stock_type_checked = $parent_stock->type_id;
632 $organism_id_checked = $parent_stock->organism_id();
635 #create the plot, if plot given
636 my $new_plot_id;
637 if ($plot_name) {
638 my @plot_stock_props = (
639 { type_id => $self->get_replicate_cvterm_id, value => $rep_number },
640 { type_id => $self->get_block_cvterm_id, value => $block_number },
641 { type_id => $self->get_plot_number_cvterm_id, value => $plot_number }
643 if ($is_a_control) {
644 push @plot_stock_props, { type_id => $self->get_is_control_cvterm_id, value => $is_a_control };
646 if ($range_number) {
647 push @plot_stock_props, { type_id => $self->get_range_cvterm_id, value => $range_number };
649 if ($row_number) {
650 push @plot_stock_props, { type_id => $self->get_row_number_cvterm_id, value => $row_number };
652 if ($col_number) {
653 push @plot_stock_props, { type_id => $self->get_col_number_cvterm_id, value => $col_number };
655 if ($well_is_blank) {
656 push @plot_stock_props, { type_id => $self->get_is_blank_cvterm_id, value => $well_is_blank };
658 if ($well_concentration) {
659 push @plot_stock_props, { type_id => $self->get_concentration_cvterm_id, value => $well_concentration };
661 if ($well_volume) {
662 push @plot_stock_props, { type_id => $self->get_volume_cvterm_id, value => $well_volume };
664 if ($well_extraction) {
665 push @plot_stock_props, { type_id => $self->get_extraction_cvterm_id, value => $well_extraction };
667 if ($well_tissue_type) {
668 push @plot_stock_props, { type_id => $self->get_tissue_type_cvterm_id, value => $well_tissue_type };
670 if ($well_dna_person) {
671 push @plot_stock_props, { type_id => $self->get_dna_person_cvterm_id, value => $well_dna_person };
673 if ($acquisition_date) {
674 push @plot_stock_props, { type_id => $self->get_acquisition_date_cvterm_id, value => $acquisition_date };
676 if ($notes) {
677 push @plot_stock_props, { type_id => $self->get_notes_cvterm_id, value => $notes };
679 if ($ncbi_taxonomy_id) {
680 push @plot_stock_props, { type_id => $self->get_ncbi_taxonomy_id_cvterm_id, value => $ncbi_taxonomy_id };
682 if ($additional_info) {
683 push @plot_stock_props, { type_id => $additional_info_type_id, value => $additional_info };
685 if ($facility_identifier) {
686 push @plot_stock_props, { type_id => $self->get_facility_identifier_cvterm_id, value => $facility_identifier };
689 my @plot_subjects;
690 my @plot_objects;
692 my $parent_stock;
693 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $stock_id_checked };
695 # For genotyping plate, if the well tissue_sample is sourced from a plot, then we store relationships between the tissue_sample and the plot, and the tissue sample and the plot's accession if it exists.
696 if ($stock_type_checked == $self->get_plot_cvterm_id){
697 my $parent_plot_accession_rs = $chado_schema->resultset("Stock::StockRelationship")->search({
698 'me.subject_id'=>$stock_id_checked,
699 'me.type_id'=>$self->get_plot_of_cvterm_id,
700 'object.type_id'=>$self->get_accession_cvterm_id
701 }, {join => 'object'});
702 if ($parent_plot_accession_rs->count > 1){
703 die "Plot $stock_id_checked is linked to more than one accession!\n"
705 if ($parent_plot_accession_rs->count == 1){
706 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $parent_plot_accession_rs->first->object_id };
709 # For genotyping plate, if the well tissue_sample is sourced from a plant, then we store relationships between the tissue_sample and the plant, and the tissue_sample and the plant's plot if it exists, and the tissue sample and the plant's accession if it exists.
710 if ($stock_type_checked == $self->get_plant_cvterm_id){
711 my $parent_plant_accession_rs = $chado_schema->resultset("Stock::StockRelationship")->search({
712 'me.subject_id'=>$stock_id_checked,
713 'me.type_id'=>$self->get_plant_of_cvterm_id,
714 'object.type_id'=>$self->get_accession_cvterm_id
715 }, {join => "object"});
716 if ($parent_plant_accession_rs->count > 1){
717 die "Plant $stock_id_checked is linked to more than one accession!\n"
719 if ($parent_plant_accession_rs->count == 1){
720 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $parent_plant_accession_rs->first->object_id };
722 my $parent_plot_of_plant_rs = $chado_schema->resultset("Stock::StockRelationship")->search({
723 'me.subject_id'=>$stock_id_checked,
724 'me.type_id'=>$self->get_plant_of_cvterm_id,
725 'object.type_id'=>$self->get_plot_cvterm_id
726 }, {join => "object"});
727 if ($parent_plot_of_plant_rs->count > 1){
728 die "Plant $stock_id_checked is linked to more than one plot!\n"
730 if ($parent_plot_of_plant_rs->count == 1){
731 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $parent_plot_of_plant_rs->first->object_id };
734 # For genotyping plate, if the well tissue_sample is sourced from another tissue_sample, then we store relationships between the new tissue_sample and the source tissue_sample, and the new tissue_sample and the tissue_sample's plant if it exists, and the new tissue_sample and the tissue_sample's plot if it exists, and the new tissue sample and the tissue_sample's accession if it exists.
735 if ($stock_type_checked == $self->get_tissue_sample_cvterm_id){
736 my $parent_tissue_sample_accession_rs = $chado_schema->resultset("Stock::StockRelationship")->search({
737 'me.subject_id'=>$stock_id_checked,
738 'me.type_id'=>$self->get_tissue_sample_of_cvterm_id,
739 'object.type_id'=>$self->get_accession_cvterm_id
740 }, {join => "object"});
741 if ($parent_tissue_sample_accession_rs->count > 1){
742 die "Tissue_sample $stock_id_checked is linked to more than one accession!\n"
744 if ($parent_tissue_sample_accession_rs->count == 1){
745 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $parent_tissue_sample_accession_rs->first->object_id };
747 my $parent_plot_of_tissue_sample_rs = $chado_schema->resultset("Stock::StockRelationship")->search({
748 'me.subject_id'=>$stock_id_checked,
749 'me.type_id'=>$self->get_tissue_sample_of_cvterm_id,
750 'object.type_id'=>$self->get_plot_cvterm_id
751 }, {join => "object"});
752 if ($parent_plot_of_tissue_sample_rs->count > 1){
753 die "Tissue_sample $stock_id_checked is linked to more than one plot!\n"
755 if ($parent_plot_of_tissue_sample_rs->count == 1){
756 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $parent_plot_of_tissue_sample_rs->first->object_id };
758 my $parent_plant_of_tissue_sample_rs = $chado_schema->resultset("Stock::StockRelationship")->search({
759 'me.subject_id'=>$stock_id_checked,
760 'me.type_id'=>$self->get_tissue_sample_of_cvterm_id,
761 'object.type_id'=>$self->get_plant_cvterm_id
762 }, {join => "object"});
763 if ($parent_plant_of_tissue_sample_rs->count > 1){
764 die "Tissue_sample $stock_id_checked is linked to more than one plant!\n"
766 if ($parent_plant_of_tissue_sample_rs->count == 1){
767 push @plot_subjects, { type_id => $stock_rel_type_id, object_id => $parent_plant_of_tissue_sample_rs->first->object_id };
771 my @plot_nd_experiment_stocks = (
772 { nd_experiment_id => $nd_experiment_id, type_id => $self->get_nd_experiment_type_id }
775 #print STDERR "STOCK TYPE ID NOW: $stock_type_id\n";
776 my $plot_params = {
777 organism_id => $organism_id_checked,
778 name => $plot_name,
779 uniquename => $plot_name,
780 type_id => $stock_type_id,
781 stockprops => \@plot_stock_props,
782 stock_relationship_subjects => \@plot_subjects,
783 stock_relationship_objects => \@plot_objects,
784 nd_experiment_stocks => \@plot_nd_experiment_stocks,
786 my $plot;
787 if (! defined $plant_names || scalar $plant_names eq 0) {
788 $plot = $stock_rs->create($plot_params);
789 } else {
790 $plot = $stock_rs->find_or_create($plot_params);
792 $new_plot_id = $plot->stock_id();
793 $new_stock_ids_hash{$plot_name} = $new_plot_id;
795 my %design = %{$self->get_design()};
796 my $sp_person_id = $self->get_owner_id;
797 my $username = $self->get_operator;
798 my $stock = CXGN::Stock->new({schema=>$chado_schema,stock_id=>$new_plot_id});
799 $stock->associate_owner($sp_person_id,$sp_person_id,$username,"");
801 if ($seedlot_stock_id && $seedlot_name){
802 my $transaction = CXGN::Stock::Seedlot::Transaction->new(schema => $chado_schema);
803 $transaction->from_stock([$seedlot_stock_id, $seedlot_name]);
804 $transaction->to_stock([$plot->stock_id(), $plot->uniquename()]);
805 if ($num_seed_per_plot){
806 $transaction->amount($num_seed_per_plot);
808 if ($weight_gram_seed_per_plot){
809 $transaction->weight_gram($weight_gram_seed_per_plot);
811 $transaction->timestamp($timestamp);
812 my $description = "Created Trial: ".$self->get_trial_name." Plot: ".$plot->uniquename;
813 $transaction->description($description);
814 $transaction->operator($self->get_operator);
815 my $transaction_id = $transaction->store();
816 my $sl = CXGN::Stock::Seedlot->new(schema=>$chado_schema, seedlot_id=>$seedlot_stock_id);
817 $sl->set_current_count_property();
818 $sl->set_current_weight_property();
822 #Create plant entry if given. Currently this is for the greenhouse trial creation and splitplot trial creation.
823 if ($plant_names) {
824 my $plant_index_number = 1;
825 foreach my $plant_name (@$plant_names) {
827 my @plant_stock_props = (
828 { type_id => $self->get_plant_index_number_cvterm_id, value => $plant_index_number },
829 { type_id => $self->get_replicate_cvterm_id, value => $rep_number },
830 { type_id => $self->get_block_cvterm_id, value => $block_number },
831 { type_id => $self->get_plot_number_cvterm_id, value => $plot_number }
833 if ($is_a_control) {
834 push @plant_stock_props, { type_id => $self->get_is_control_cvterm_id, value => $is_a_control };
836 if ($range_number) {
837 push @plant_stock_props, { type_id => $self->get_range_cvterm_id, value => $range_number };
839 if ($row_number) {
840 push @plant_stock_props, { type_id => $self->get_row_number_cvterm_id, value => $row_number };
842 if ($col_number) {
843 push @plant_stock_props, { type_id => $self->get_col_number_cvterm_id, value => $col_number };
845 if ($additional_info) {
846 push @plant_stock_props, { type_id => $additional_info_type_id, value => $additional_info };
849 my @plant_objects = (
850 { type_id => $self->get_plant_of_cvterm_id, subject_id => $new_plot_id }
852 my @plant_subjects = (
853 { type_id => $self->get_plant_of_cvterm_id, object_id => $stock_id_checked }
855 my @plant_nd_experiment_stocks = (
856 { type_id => $self->get_nd_experiment_type_id, nd_experiment_id => $nd_experiment_id }
860 my $plant = $stock_rs->create({
861 organism_id => $organism_id_checked,
862 name => $plant_name,
863 uniquename => $plant_name,
864 type_id => $self->get_plant_cvterm_id,
865 stockprops => \@plant_stock_props,
866 stock_relationship_subjects => \@plant_subjects,
867 stock_relationship_objects => \@plant_objects,
868 nd_experiment_stocks => \@plant_nd_experiment_stocks,
870 $new_stock_ids_hash{$plant_name} = $plant->stock_id();
871 $plant_index_number++;
874 # Set the study to have plant entries
875 if (scalar @$plant_names > 0) {
876 my $study = $chado_schema->resultset('Project::Project')->find( { project_id => $self->get_trial_id() });
877 $study->create_projectprops({ 'project_has_plant_entries' => 1 });
880 #Create subplot entry if given. Currently this is for the splitplot trial creation.
881 if ($subplot_names) {
882 my $subplot_index_number = 1;
883 foreach my $subplot_name (@$subplot_names) {
884 my @subplot_stockprops = (
885 { type_id => $self->get_subplot_index_number_cvterm_id, value => $subplot_index_number },
886 { type_id => $self->get_replicate_cvterm_id, value => $rep_number },
887 { type_id => $self->get_block_cvterm_id, value => $block_number },
888 { type_id => $self->get_plot_number_cvterm_id, value => $plot_number }
890 if ($is_a_control) {
891 push @subplot_stockprops, { type_id => $self->get_is_control_cvterm_id, value => $is_a_control };
893 if ($range_number) {
894 push @subplot_stockprops, { type_id => $self->get_range_cvterm_id, value => $range_number };
896 if ($row_number) {
897 push @subplot_stockprops, { type_id => $self->get_row_number_cvterm_id, value => $row_number };
899 if ($col_number) {
900 push @subplot_stockprops, { type_id => $self->get_col_number_cvterm_id, value => $col_number };
903 my @subplot_objects = (
904 { type_id => $self->get_subplot_of_cvterm_id, subject_id => $new_plot_id }
906 my @subplot_subjects = (
907 { type_id => $self->get_subplot_of_cvterm_id, object_id => $stock_id_checked }
909 my @subplot_nd_experiment_stocks = (
910 { type_id => $self->get_nd_experiment_type_id, nd_experiment_id => $nd_experiment_id }
913 if ($subplots_plant_names){
914 my $subplot_plants = $subplots_plant_names->{$subplot_name};
915 foreach (@$subplot_plants) {
916 my $plant_stock_id = $new_stock_ids_hash{$_};
917 push @subplot_objects, { type_id => $self->get_plant_of_subplot_cvterm_id, subject_id => $plant_stock_id };
921 my $subplot = $stock_rs->create({
922 organism_id => $organism_id_checked,
923 name => $subplot_name,
924 uniquename => $subplot_name,
925 type_id => $self->get_subplot_cvterm_id,
926 stockprops => \@subplot_stockprops,
927 stock_relationship_subjects => \@subplot_subjects,
928 stock_relationship_objects => \@subplot_objects,
929 nd_experiment_stocks => \@subplot_nd_experiment_stocks,
931 $new_stock_ids_hash{$subplot_name} = $subplot->stock_id();
932 $subplot_index_number++;
938 if (exists($design{'treatments'})){
939 print STDERR "Saving treatments\n";
940 my %treatments_hash = %{$design{'treatments'}};
942 foreach my $treatment_name (sort keys %treatments_hash) {
943 my $stock_names;
944 my $management_factor_type;
945 my $management_factor_year;
946 my $management_factor_date;
947 my $management_factor_description = '';
948 # my %info_hashes = %{$treatments_hash{$treatment_name}};
949 my $info_value = $treatments_hash{$treatment_name};
950 my $info_type = ref($info_value);
951 if ($info_type eq 'HASH'){
952 my %info_hashes = %$info_value;
953 $stock_names = $info_hashes{'new_treatment_stocks'};
954 $management_factor_type = $info_hashes{'new_treatment_type'};
955 $management_factor_year = $info_hashes{'new_treatment_year'};
956 $management_factor_date = $info_hashes{'new_treatment_date'};
957 $management_factor_description = $info_hashes{'new_treatment_description'} || 'No description';
958 } else {
959 $stock_names = $treatments_hash{$treatment_name};
961 # print STDERR "STOCK NAMES =".Dumper($stock_names)."\n";
962 my @treatment_nd_experiment_stocks;
963 foreach (@$stock_names){
964 my $stock_id;
965 if (exists($new_stock_ids_hash{$_})){
966 $stock_id = $new_stock_ids_hash{$_};
967 } else {
968 $stock_id = $chado_schema->resultset("Stock::Stock")->find({uniquename=>$_})->stock_id();
970 push @treatment_nd_experiment_stocks, { type_id => $self->get_treatment_nd_experiment_type_id, stock_id => $stock_id };
973 my $nd_experiment = $chado_schema->resultset('NaturalDiversity::NdExperiment')->create({
974 nd_geolocation_id => $nd_geolocation_id,
975 type_id => $self->get_treatment_nd_experiment_type_id,
976 nd_experiment_stocks => \@treatment_nd_experiment_stocks
979 my @treatment_project_props = (
980 { type_id => $self->get_project_design_cvterm_id, value => 'treatment' }
983 if ($self->get_new_treatment_has_plant_entries){
984 push @treatment_project_props, { type_id => $self->get_has_plants_cvterm, value => $self->get_new_treatment_has_plant_entries };
986 if ($self->get_new_treatment_has_subplot_entries){
987 push @treatment_project_props, { type_id => $self->get_has_subplots_cvterm, value => $self->get_new_treatment_has_subplot_entries };
989 if ($self->get_new_treatment_has_tissue_sample_entries){
990 push @treatment_project_props, { type_id => $self->get_has_tissues_cvterm, value => $self->get_new_treatment_has_tissue_sample_entries };
992 if (defined $management_factor_type){
993 push @treatment_project_props, { type_id => $self->get_management_factor_type_cvterm_id, value => $management_factor_type };
995 if (defined $management_factor_year){
996 push @treatment_project_props, { type_id => $self->get_management_factor_year_cvterm_id, value => $management_factor_year };
997 } else {
998 my $t = CXGN::Trial->new({
999 bcs_schema => $chado_schema,
1000 trial_id => $self->get_trial_id
1002 push @treatment_project_props, { type_id => $self->get_management_factor_year_cvterm_id, value => $t->get_year() };
1006 if (defined $management_factor_date){
1007 push @treatment_project_props, { type_id => $self->get_management_factor_date_cvterm_id, value => $management_factor_date };
1010 my @treatment_nd_experiment_project = (
1011 { nd_experiment_id => $nd_experiment->nd_experiment_id }
1014 my @treatment_relationships = (
1015 { type_id => $self->get_trial_treatment_relationship_cvterm_id, object_project_id => $self->get_trial_id }
1018 #Create a project for each treatment_name
1019 my $project_treatment_name = $self->get_trial_name()."_".$treatment_name;
1020 my $treatment_project = $chado_schema->resultset('Project::Project')->create({
1021 name => $project_treatment_name,
1022 description => $management_factor_description,
1023 projectprops => \@treatment_project_props,
1024 project_relationship_subject_projects => \@treatment_relationships,
1025 nd_experiment_projects => \@treatment_nd_experiment_project
1028 if ($self->get_new_treatment_date()) {
1029 my $management_factor_t = CXGN::Trial->new({
1030 bcs_schema => $chado_schema,
1031 trial_id => $treatment_project->project_id()
1033 $management_factor_t->set_management_factor_date($self->get_new_treatment_date() );
1038 print STDERR "Design Stored ".localtime."\n";
1041 my $transaction_error;
1043 try {
1044 $chado_schema->txn_do($coderef);
1046 catch {
1047 print STDERR "Transaction Error: $_\n";
1048 $transaction_error = $_;
1050 return $transaction_error;