2 package SGN
::Controller
::AJAX
::TrialMetadata
;
7 use Bio
::Chado
::Schema
;
8 use List
::Util qw
| any
|;
13 BEGIN { extends
'Catalyst::Controller::REST' }
16 default => 'application/json',
18 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
23 isa
=> 'DBIx::Class::Schema',
28 sub trial
: Chained
('/') PathPart
('ajax/breeders/trial') CaptureArgs
(1) {
33 $c->stash->{trial_id
} = $trial_id;
34 $c->stash->{schema
} = $c->dbic_schema("Bio::Chado::Schema");
35 $c->stash->{trial
} = CXGN
::Trial
->new( { bcs_schema
=> $c->stash->{schema
}, trial_id
=> $trial_id });
37 if (!$c->stash->{trial
}) {
38 $c->stash->{rest
} = { error
=> "The specified trial with id $trial_id does not exist" };
44 =head2 delete_trial_by_file
55 sub delete_trial_data
: Local
() ActionClass
('REST');
57 sub delete_trial_data_GET
: Chained
('trial') PathPart
('delete') Args
(1) {
62 if ($self->delete_privileges_denied($c)) {
63 $c->stash->{rest
} = { error
=> "You have insufficient access privileges to delete trial data." };
69 if ($datatype eq 'phenotypes') {
70 $error = $c->stash->{trial
}->delete_phenotype_metadata($c->dbic_schema("CXGN::Metadata::Schema"), $c->dbic_schema("CXGN::Phenome::Schema"));
71 $error .= $c->stash->{trial
}->delete_phenotype_data();
74 elsif ($datatype eq 'layout') {
75 $error = $c->stash->{trial
}->delete_metadata($c->dbic_schema("CXGN::Metadata::Schema"), $c->dbic_schema("CXGN::Phenome::Schema"));
76 $error = $c->stash->{trial
}->delete_field_layout();
78 elsif ($datatype eq 'entry') {
79 $error = $c->stash->{trial
}->delete_project_entry();
82 $c->stash->{rest
} = { error
=> "unknown delete action for $datatype" };
86 $c->stash->{rest
} = { error
=> $error };
89 $c->stash->{rest
} = { message
=> "Successfully deleted trial data.", success
=> 1 };
92 sub trial_details
: Chained
('trial') PathPart
('details') Args
(0) ActionClass
('REST') {};
94 sub trial_details_GET
{
98 my $trial = $c->stash->{trial
};
100 $c->stash->{rest
} = { details
=> $trial->get_details() };
104 sub trial_details_POST
{
108 my @categories = $c->req->param("categories[]");
111 foreach my $category (@categories) {
112 $details->{$category} = $c->req->param("details[$category]");
116 $c->stash->{rest
} = { error
=> "No values were edited, so no changes could be made for this trial's details." };
120 print STDERR
"Here are the deets: " . Dumper
($details) . "\n";
123 if (!($c->user()->check_roles('curator') || $c->user()->check_roles('submitter'))) {
124 $c->stash->{rest
} = { error
=> 'You do not have the required privileges to edit the trial details of this trial.' };
128 my $trial_id = $c->stash->{trial_id
};
129 my $trial = $c->stash->{trial
};
130 my $program_object = CXGN
::BreedersToolbox
::Projects
->new( { schema
=> $c->stash->{schema
} });
131 my $breeding_program = $program_object->get_breeding_programs_by_trial($trial_id);
133 if (! ($c->user() && ($c->user->check_roles("curator") || $c->user->check_roles($breeding_program)))) {
134 $c->stash->{rest
} = { error
=> "You need to be logged in with sufficient privileges to change the details of this trial." };
138 # set each new detail that is defined
140 if ($details->{name
}) { $trial->set_name($details->{name
}); }
141 if ($details->{breeding_program
}) { $trial->set_breeding_program($details->{breeding_program
}); }
142 if ($details->{location
}) { $trial->set_location($details->{location
}); }
143 if ($details->{year
}) { $trial->set_year($details->{year
}); }
144 if ($details->{type
}) { $trial->set_project_type($details->{type
}); }
145 if ($details->{planting_date
}) {
146 if ($details->{planting_date
} eq 'remove') { $trial->remove_planting_date($trial->get_planting_date()); }
147 else { $trial->set_planting_date($details->{planting_date
}); }
149 if ($details->{harvest_date
}) {
150 if ($details->{harvest_date
} eq 'remove') { $trial->remove_harvest_date($trial->get_harvest_date()); }
151 else { $trial->set_harvest_date($details->{harvest_date
}); }
153 if ($details->{description
}) { $trial->set_description($details->{description
}); }
157 $c->stash->{rest
} = { error
=> "An error occurred setting the new trial details: $@" };
160 $c->stash->{rest
} = { success
=> 1 };
164 sub traits_assayed
: Chained
('trial') PathPart
('traits_assayed') Args
(0) {
167 my $stock_type = $c->req->param('stock_type');
169 my @traits_assayed = $c->stash->{trial
}->get_traits_assayed($stock_type);
170 $c->stash->{rest
} = { traits_assayed
=> \
@traits_assayed };
174 sub phenotype_summary
: Chained
('trial') PathPart
('phenotypes') Args
(0) {
178 my $round = Math
::Round
::Var
->new(0.01);
179 my $dbh = $c->dbc->dbh();
180 my $trial_id = $c->stash->{trial_id
};
182 my $h = $dbh->prepare("SELECT (((cvterm.name::text || '|'::text) || db.name::text) || ':'::text)
183 || dbxref.accession::text AS trait,
185 count(phenotype.value),
186 to_char(avg(phenotype.value::real), 'FM999990.990'),
187 to_char(max(phenotype.value::real), 'FM999990.990'),
188 to_char(min(phenotype.value::real), 'FM999990.990'),
189 to_char(stddev(phenotype.value::real), 'FM999990.990')
191 JOIN phenotype ON (cvterm_id=cvalue_id)
192 JOIN nd_experiment_phenotype USING(phenotype_id)
193 JOIN nd_experiment_project USING(nd_experiment_id)
194 JOIN dbxref ON cvterm.dbxref_id = dbxref.dbxref_id JOIN db ON dbxref.db_id = db.db_id
196 AND phenotype.value~?
197 GROUP BY (((cvterm.name::text || '|'::text) || db.name::text) || ':'::text)
198 || dbxref.accession::text, cvterm.cvterm_id;");
200 my $numeric_regex = '^[0-9]+([,.][0-9]+)?$';
201 $h->execute($c->stash->{trial_id
}, $numeric_regex);
205 while (my ($trait, $trait_id, $count, $average, $max, $min, $stddev) = $h->fetchrow_array()) {
207 my $cv = ($stddev / $average) * 100;
208 $cv = $round->round($cv) . '%';
209 $average = $round->round($average);
210 $min = $round->round($min);
211 $max = $round->round($max);
212 $stddev = $round->round($stddev);
214 push @phenotype_data, [ qq{<a href
="/cvterm/$trait_id/view">$trait</a
>}, $average, $min, $max, $stddev, $cv, $count, qq{<a href
="#raw_data_histogram_well" onclick
="trait_summary_hist_change($trait_id)"><span
class="glyphicon glyphicon-stats"></span></a>} ];
217 $c->stash->{rest
} = { data
=> \
@phenotype_data };
220 sub trait_histogram
: Chained
('trial') PathPart
('trait_histogram') Args
(1) {
223 my $trait_id = shift;
225 my @data = $c->stash->{trial
}->get_phenotypes_for_trait($trait_id);
227 $c->stash->{rest
} = { data
=> \
@data };
230 sub get_trial_folder
:Chained
('trial') PathPart
('folder') Args
(0) {
234 if (!($c->user()->check_roles('curator') || $c->user()->check_roles('submitter'))) {
235 $c->stash->{rest
} = { error
=> 'You do not have the required privileges to edit the trial type of this trial.' };
239 my $project_parent = $c->stash->{trial
}->get_folder();
241 $c->stash->{rest
} = { folder
=> [ $project_parent->project_id(), $project_parent->name() ] };
245 sub trial_accessions
: Chained
('trial') PathPart
('accessions') Args
(0) {
248 my $schema = $c->dbic_schema("Bio::Chado::Schema");
250 my $trial = CXGN
::Trial
->new( { bcs_schema
=> $schema, trial_id
=> $c->stash->{trial_id
} });
252 my @data = $trial->get_accessions();
254 $c->stash->{rest
} = { accessions
=> \
@data };
257 sub trial_controls
: Chained
('trial') PathPart
('controls') Args
(0) {
260 my $schema = $c->dbic_schema("Bio::Chado::Schema");
262 my $trial = CXGN
::Trial
->new( { bcs_schema
=> $schema, trial_id
=> $c->stash->{trial_id
} });
264 my @data = $trial->get_controls();
266 $c->stash->{rest
} = { accessions
=> \
@data };
269 sub trial_plots
: Chained
('trial') PathPart
('plots') Args
(0) {
272 my $schema = $c->dbic_schema("Bio::Chado::Schema");
274 my $trial = CXGN
::Trial
->new( { bcs_schema
=> $schema, trial_id
=> $c->stash->{trial_id
} });
276 my @data = $trial->get_plots();
278 $c->stash->{rest
} = { plots
=> \
@data };
281 sub trial_plants
: Chained
('trial') PathPart
('plants') Args
(0) {
284 my $schema = $c->dbic_schema("Bio::Chado::Schema");
286 my $trial = CXGN
::Trial
->new( { bcs_schema
=> $schema, trial_id
=> $c->stash->{trial_id
} });
288 my @data = $trial->get_plants();
290 $c->stash->{rest
} = { plants
=> \
@data };
293 sub trial_design
: Chained
('trial') PathPart
('design') Args
(0) {
296 my $schema = $c->dbic_schema("Bio::Chado::Schema");
298 my $layout = CXGN
::Trial
::TrialLayout
->new({ schema
=> $schema, trial_id
=>$c->stash->{trial_id
} });
300 my $design = $layout->get_design();
301 my $design_type = $layout->get_design_type();
302 my $plot_dimensions = $layout->get_plot_dimensions();
304 my $plot_length = '';
305 if ($plot_dimensions->[0]) {
306 $plot_length = $plot_dimensions->[0];
310 if ($plot_dimensions->[1]){
311 $plot_width = $plot_dimensions->[1];
314 my $plants_per_plot = '';
315 if ($plot_dimensions->[2]){
316 $plants_per_plot = $plot_dimensions->[2];
319 my $block_numbers = $layout->get_block_numbers();
320 my $number_of_blocks = '';
321 if ($block_numbers) {
322 $number_of_blocks = scalar(@
{$block_numbers});
325 my $replicate_numbers = $layout->get_replicate_numbers();
326 my $number_of_replicates = '';
327 if ($replicate_numbers) {
328 $number_of_replicates = scalar(@
{$replicate_numbers});
331 $c->stash->{rest
} = { design_type
=> $design_type, num_blocks
=> $number_of_blocks, num_reps
=> $number_of_replicates, plot_length
=> $plot_length, plot_width
=> $plot_width, plants_per_plot
=> $plants_per_plot, design
=> $design };
334 sub get_spatial_layout
: Chained
('trial') PathPart
('coords') Args
(0) {
338 my $schema = $c->dbic_schema("Bio::Chado::Schema");
340 my $layout = CXGN
::Trial
::TrialLayout
->new(
343 trial_id
=>$c->stash->{trial_id
}
346 my $design = $layout-> get_design
();
348 #print STDERR Dumper($design);
351 foreach my $plot_number (keys %{$design}) {
353 plot_id
=> $design->{$plot_number}->{plot_id
},
354 plot_number
=> $plot_number,
355 row_number
=> $design->{$plot_number}->{row_number
},
356 col_number
=> $design->{$plot_number}->{col_number
},
357 block_number
=> $design->{$plot_number}-> {block_number
},
358 rep_number
=> $design->{$plot_number}-> {rep_number
},
359 plot_name
=> $design->{$plot_number}-> {plot_name
},
360 accession_name
=> $design->{$plot_number}-> {accession_name
},
366 my @row_numbers = ();
367 my @col_numbers = ();
368 my @rep_numbers = ();
369 my @block_numbers = ();
370 my @accession_name = ();
374 my @plot_number = ();
377 foreach $my_hash (@layout_info) {
378 if ($my_hash->{'row_number'}) {
379 if ($my_hash->{'row_number'} =~ m/\d+/) {
380 $array_msg[$my_hash->{'row_number'}-1][$my_hash->{'col_number'}-1] = "rep_number: ".$my_hash->{'rep_number'}."\nblock_number: ".$my_hash->{'block_number'}."\nrow_number: ".$my_hash->{'row_number'}."\ncol_number: ".$my_hash->{'col_number'}."\naccession_name: ".$my_hash->{'accession_name'};
383 $plot_id[$my_hash->{'row_number'}-1][$my_hash->{'col_number'}-1] = $my_hash->{'plot_id'};
384 #$plot_id[$my_hash->{'plot_number'}] = $my_hash->{'plot_id'};
385 $plot_number[$my_hash->{'row_number'}-1][$my_hash->{'col_number'}-1] = $my_hash->{'plot_number'};
386 #$plot_number[$my_hash->{'plot_number'}] = $my_hash->{'plot_number'};
393 # Looping through the hash and printing out all the hash elements.
395 foreach $my_hash (@layout_info) {
396 push @col_numbers, $my_hash->{'col_number'};
397 push @row_numbers, $my_hash->{'row_number'};
398 #push @plot_id, $my_hash->{'plot_id'};
399 #push @plot_number, $my_hash->{'plot_number'};
400 push @rep_numbers, $my_hash->{'rep_number'};
401 push @block_numbers, $my_hash->{'block_number'};
402 push @accession_name, $my_hash->{'accession_name'};
403 push @plot_name, $my_hash->{'plot_name'};
409 $max_col = max
( @col_numbers ) if (@col_numbers);
412 $max_row = max
( @row_numbers ) if (@row_numbers);
415 #print STDERR Dumper \@layout_info;
417 $c->stash->{rest
} = { coord_row
=> \
@row_numbers,
418 coords
=> \
@layout_info,
419 coord_col
=> \
@col_numbers,
422 plot_msg
=> \
@array_msg,
423 rep
=> \
@rep_numbers,
424 block
=> \
@block_numbers,
425 accessions
=> \
@accession_name,
426 plot_name
=> \
@plot_name,
427 plot_id
=> \
@plot_id,
428 plot_number
=> \
@plot_number
433 sub compute_derive_traits
: Path
('/ajax/phenotype/delete_field_coords') Args
(0) {
437 my $trial_id = $c->req->param('trial_id');
438 print "TRIALID: $trial_id\n";
440 my $schema = $c->dbic_schema('Bio::Chado::Schema');
441 my $dbh = $c->dbc->dbh();
444 print STDERR
"User not logged in... not deleting field map.\n";
445 $c->stash->{rest
} = {error
=> "You need to be logged in to delete field map." };
449 if (!any
{ $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) {
450 $c->stash->{rest
} = {error
=> "You have insufficient privileges to delete field map." };
454 my $h = $dbh->prepare("delete from stockprop where stockprop.stockprop_id IN (select stockprop.stockprop_id from project join nd_experiment_project using(project_id) join nd_experiment_stock using(nd_experiment_id) join stock using(stock_id) join stockprop on(stock.stock_id=stockprop.stock_id) where (stockprop.type_id IN (select cvterm_id from cvterm where name='col_number') or stockprop.type_id IN (select cvterm_id from cvterm where name='row_number')) and project.project_id=? and stock.type_id IN (select cvterm_id from cvterm join cv using(cv_id) where cv.name = 'stock_type' and cvterm.name ='plot'));");
455 my ($row_number, $col_number, $cvterm_id, @cvterm );
456 $h->execute($trial_id);
458 $c->stash->{rest
} = {success
=> 1};
463 sub create_plant_subplots
: Chained
('trial') PathPart
('create_subplots') Args
(0) {
466 my $plants_per_plot = $c->req->param("plants_per_plot") || 8;
468 if (my $error = $self->delete_privileges_denied($c)) {
469 $c->stash->{rest
} = { error
=> $error };
473 if (!$plants_per_plot || $plants_per_plot > 50) {
474 $c->stash->{rest
} = { error
=> "Plants per plot number is required and must be smaller than 20." };
478 my $t = CXGN
::Trial
->new( { bcs_schema
=> $c->dbic_schema("Bio::Chado::Schema"), trial_id
=> $c->stash->{trial_id
} });
480 if ($t->create_plant_entities($plants_per_plot)) {
481 $c->stash->{rest
} = {success
=> 1};
484 $c->stash->{rest
} = { error
=> "Error creating plant entries in controller." };
491 sub delete_privileges_denied
{
495 my $trial_id = $c->stash->{trial_id
};
497 if (! $c->user) { return "Login required for delete functions."; }
498 my $user_id = $c->user->get_object->get_sp_person_id();
500 if ($c->user->check_roles('curator')) {
504 my $breeding_programs = $c->stash->{trial
}->get_breeding_programs();
506 if ( ($c->user->check_roles('submitter')) && ( $c->user->check_roles($breeding_programs->[0]->[1]))) {
509 return "You have insufficient privileges to modify or delete this trial.";
512 # loading field coordinates
514 sub upload_trial_coordinates
: Path
('/ajax/breeders/trial/coordsupload') Args
(0) {
520 print STDERR
"User not logged in... not uploading coordinates.\n";
521 $c->stash->{rest
} = {error
=> "You need to be logged in to upload coordinates." };
525 if (!any
{ $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) {
526 $c->stash->{rest
} = {error
=> "You have insufficient privileges to add coordinates." };
530 my $time = DateTime
->now();
531 my $user_id = $c->user()->get_object()->get_sp_person_id();
532 my $user_name = $c->user()->get_object()->get_username();
533 my $timestamp = $time->ymd()."_".$time->hms();
534 my $subdirectory = 'trial_coords_upload';
536 my $upload = $c->req->upload('trial_coordinates_uploaded_file');
537 my $upload_tempfile = $upload->tempname;
539 my $upload_original_name = $upload->filename();
542 my $uploader = CXGN
::UploadFile
->new();
547 # Store uploaded temporary file in archive
548 print STDERR
"TEMP FILE: $upload_tempfile\n";
549 my $archived_filename_with_path = $uploader->archive($c, $subdirectory, $upload_tempfile, $upload_original_name, $timestamp);
551 if (!$archived_filename_with_path) {
552 $c->stash->{rest
} = {error
=> "Could not save file $upload_original_name in archive",};
556 $md5 = $uploader->get_md5($archived_filename_with_path);
557 unlink $upload_tempfile;
559 # open file and remove return of line
561 open(my $F, "<", $archived_filename_with_path) || die "Can't open archive file $archived_filename_with_path";
562 my $schema = $c->dbic_schema("Bio::Chado::Schema");
567 my ($plot,$row,$col) = split /\t/ ;
569 my $rs = $schema->resultset("Stock::Stock")->search({uniquename
=> $plot });
571 if ($rs->count()== 1) {
572 my $r = $rs->first();
573 print STDERR
"The plots $plot was found.\n Loading row $row col $col\n";
574 $r->create_stockprops({row_number
=> $row, col_number
=> $col}, {autocreate
=> 1});
579 print STDERR
"WARNING! $plot was not found in the database.\n";
585 $c->stash->{rest
} = {success
=> 1};