add date based queries for phenotype download.
[sgn.git] / lib / SGN / Controller / AJAX / TrialMetadata.pm
blob03d934e5dfed9e69356a9907196df357fd291c4c
1 package SGN::Controller::AJAX::TrialMetadata;
3 use Moose;
4 use Data::Dumper;
5 use Bio::Chado::Schema;
6 use CXGN::Trial;
7 use CXGN::Trial::TrialLookup;
8 use Math::Round::Var;
9 use File::Temp 'tempfile';
10 use Text::CSV;
11 use CXGN::Trial::FieldMap;
12 use JSON;
13 use CXGN::Phenotypes::PhenotypeMatrix;
14 use CXGN::Cross;
16 use CXGN::Phenotypes::TrialPhenotype;
17 use CXGN::Login;
18 use CXGN::UploadFile;
19 use CXGN::Stock::Seedlot;
20 use CXGN::Stock::Seedlot::Transaction;
21 use File::Basename qw | basename dirname|;
22 use File::Slurp qw | read_file |;
23 use List::MoreUtils qw | :all !before !after |;
24 use Try::Tiny;
25 use CXGN::BreederSearch;
26 use CXGN::Page::FormattingHelpers qw / html_optional_show /;
27 use SGN::Image;
28 use CXGN::Trial::TrialLayoutDownload;
29 use CXGN::Genotype::DownloadFactory;
30 use POSIX qw | !qsort !bsearch |;
31 use CXGN::Phenotypes::StorePhenotypes;
32 use Statistics::Descriptive::Full;
33 use CXGN::TrialStatus;
34 use CXGN::BreedersToolbox::SoilData;
35 use CXGN::Genotype::GenotypingProject;
37 BEGIN { extends 'Catalyst::Controller::REST' }
39 __PACKAGE__->config(
40 default => 'application/json',
41 stash_key => 'rest',
42 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
45 has 'schema' => (
46 is => 'rw',
47 isa => 'DBIx::Class::Schema',
48 lazy_build => 1,
52 sub trial : Chained('/') PathPart('ajax/breeders/trial') CaptureArgs(1) {
53 my $self = shift;
54 my $c = shift;
55 my $trial_id = shift;
57 my $bcs_schema = $c->dbic_schema("Bio::Chado::Schema");
58 my $metadata_schema = $c->dbic_schema('CXGN::Metadata::Schema');
59 my $phenome_schema = $c->dbic_schema('CXGN::Phenome::Schema');
61 $c->stash->{trial_id} = $trial_id;
62 $c->stash->{schema} = $bcs_schema;
63 $c->stash->{trial} = CXGN::Trial->new({
64 bcs_schema => $bcs_schema,
65 metadata_schema => $metadata_schema,
66 phenome_schema => $phenome_schema,
67 trial_id => $trial_id
68 });
70 if (!$c->stash->{trial}) {
71 $c->stash->{rest} = { error => "The specified trial with id $trial_id does not exist" };
72 return;
75 try {
76 my %param = ( schema => $bcs_schema, trial_id => $trial_id );
77 if ($c->stash->{trial}->get_design_type() eq 'genotyping_plate'){
78 $param{experiment_type} = 'genotyping_layout';
79 } else {
80 $param{experiment_type} = 'field_layout';
82 $c->stash->{trial_layout} = CXGN::Trial::TrialLayout->new(\%param);
83 # print STDERR "Trial Layout: ".Dumper($c->stash->{trial_layout})."\n";
85 catch {
86 print STDERR "Trial Layout for $trial_id does not exist. @_\n";
91 =head2 delete_trial_by_file
92 Usage:
93 Desc:
94 Ret:
95 Args:
96 Side Effects:
97 Example:
98 =cut
100 sub delete_trial_data : Local() ActionClass('REST');
102 sub delete_trial_data_GET : Chained('trial') PathPart('delete') Args(1) {
103 my $self = shift;
104 my $c = shift;
105 my $datatype = shift;
106 my $schema = $c->dbic_schema("Bio::Chado::Schema");
107 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
108 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
110 if ($self->privileges_denied($c)) {
111 $c->stash->{rest} = { error => "You have insufficient access privileges to delete trial data." };
112 return;
115 my $error = "";
117 if ($datatype eq 'phenotypes') {
118 my $dir = $c->tempfiles_subdir('/delete_nd_experiment_ids');
119 my $temp_file_nd_experiment_id = $c->config->{basepath}."/".$c->tempfile( TEMPLATE => 'delete_nd_experiment_ids/fileXXXX');
121 $error = $c->stash->{trial}->delete_phenotype_metadata($metadata_schema, $phenome_schema);
122 $error .= $c->stash->{trial}->delete_phenotype_data($c->config->{basepath}, $c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, $temp_file_nd_experiment_id);
125 elsif ($datatype eq 'layout') {
127 my $project_relationship_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'drone_run_on_field_trial', 'project_relationship')->cvterm_id();
128 my $drone_image_check_q = "SELECT count(subject_project_id) FROM project_relationship WHERE object_project_id = ? AND type_id = ?;";
129 my $drone_image_check_h = $schema->storage->dbh()->prepare($drone_image_check_q);;
130 $drone_image_check_h->execute($c->stash->{trial_id}, $project_relationship_type_id);
131 my ($drone_run_count) = $drone_image_check_h->fetchrow_array();
133 if ($drone_run_count > 0) {
134 $c->stash->{rest} = { error => "Please delete the imaging events belonging to this field trial first!" };
135 return;
138 $error = $c->stash->{trial}->delete_metadata();
139 $error .= $c->stash->{trial}->delete_field_layout();
140 $error .= $c->stash->{trial}->delete_project_entry();
142 my $dbh = $c->dbc->dbh();
143 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
144 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
146 elsif ($datatype eq 'entry') {
147 $error = $c->stash->{trial}->delete_project_entry();
149 elsif ($datatype eq 'crossing_experiment') {
150 $error = $c->stash->{trial}->delete_empty_crossing_experiment();
152 elsif ($datatype eq 'genotyping_project') {
153 $error = $c->stash->{trial}->delete_empty_genotyping_project();
155 else {
156 $c->stash->{rest} = { error => "unknown delete action for $datatype" };
157 return;
159 if ($error) {
160 $c->stash->{rest} = { error => $error };
161 return;
163 $c->stash->{rest} = { message => "Successfully deleted trial data.", success => 1 };
166 sub trial_phenotypes_fully_uploaded : Chained('trial') PathPart('phenotypes_fully_uploaded') Args(0) ActionClass('REST') {};
168 sub trial_phenotypes_fully_uploaded_GET {
169 my $self = shift;
170 my $c = shift;
171 my $trial = $c->stash->{trial};
172 $c->stash->{rest} = { phenotypes_fully_uploaded => $trial->get_phenotypes_fully_uploaded() };
175 sub trial_phenotypes_fully_uploaded_POST {
176 my $self = shift;
177 my $c = shift;
178 my $value = $c->req->param("phenotypes_fully_uploaded");
179 my $trial = $c->stash->{trial};
180 eval {
181 $trial->set_phenotypes_fully_uploaded($value);
183 if ($@) {
184 $c->stash->{rest} = { error => "An error occurred setting phenotypes_fully_uploaded: $@" };
186 else {
187 $c->stash->{rest} = { success => 1 };
191 sub trial_details : Chained('trial') PathPart('details') Args(0) ActionClass('REST') {};
193 sub trial_details_GET {
194 my $self = shift;
195 my $c = shift;
197 my $trial = $c->stash->{trial};
198 my $planting_date = $trial->get_planting_date();
199 my $harvest_date = $trial->get_harvest_date();
200 my $get_location_noaa_station_id = $trial->get_location_noaa_station_id();
202 $c->stash->{rest} = {
203 details => {
204 planting_date => $planting_date,
205 harvest_date => $harvest_date,
206 location_noaa_station_id => $get_location_noaa_station_id
212 sub trial_details_POST {
213 my $self = shift;
214 my $c = shift;
216 my @categories = $c->req->param("categories[]");
218 my $details = {};
219 foreach my $category (@categories) {
220 $details->{$category} = $c->req->param("details[$category]");
223 if (!%{$details}) {
224 $c->stash->{rest} = { error => "No values were edited, so no changes could be made for this trial's details." };
225 return;
227 else {
228 print STDERR "Here are the deets: " . Dumper($details) . "\n";
231 #check privileges
232 print STDERR " curator status = ".$c->user()->check_roles('curator')." and submitter status = ".$c->user()->check_roles('submitter')."\n";
233 if (!($c->user()->check_roles('curator') || $c->user()->check_roles('submitter'))) {
234 $c->stash->{rest} = { error => 'You do not have the required privileges to edit trial details, trial details can only be edited by accounts with submitter or curator privileges' };
235 return;
238 my $trial_id = $c->stash->{trial_id};
239 my $trial = $c->stash->{trial};
240 my $program_object = CXGN::BreedersToolbox::Projects->new( { schema => $c->stash->{schema} });
241 my $program_ref = $program_object->get_breeding_programs_by_trial($trial_id);
243 my $program_array = @$program_ref[0];
244 my $breeding_program_name = @$program_array[1];
245 my @user_roles = $c->user->roles();
246 my %has_roles = ();
247 map { $has_roles{$_} = 1; } @user_roles;
249 print STDERR "my user roles = @user_roles and trial breeding program = $breeding_program_name \n";
251 # policy: curators can change without breeding program association
252 # submitters can change if they are associated with the breeding program
253 # users cannot change
255 if (! ( (exists($has_roles{$breeding_program_name}) && exists($has_roles{submitter})) || exists($has_roles{curator}))) {
257 # if (!exists($has_roles{$breeding_program_name})) {
258 $c->stash->{rest} = { error => "You need to be either a curator, or a submitter associated with breeding program $breeding_program_name to change the details of this trial." };
259 return;
262 # set each new detail that is defined
263 #print STDERR Dumper $details;
264 eval {
265 if ($details->{name}) { $trial->set_name($details->{name}); }
266 if ($details->{breeding_program}) { $trial->set_breeding_program($details->{breeding_program}); }
267 if ($details->{location}) { $trial->set_location($details->{location}); }
268 if ($details->{year}) { $trial->set_year($details->{year}); }
269 if ($details->{type}) { $trial->set_project_type($details->{type}); }
270 if ($details->{planting_date}) {
271 if ($details->{planting_date} eq 'remove') { $trial->remove_planting_date($trial->get_planting_date()); }
272 else { $trial->set_planting_date($details->{planting_date}); }
274 if ($details->{harvest_date}) {
275 if ($details->{harvest_date} eq 'remove') { $trial->remove_harvest_date($trial->get_harvest_date()); }
276 else { $trial->set_harvest_date($details->{harvest_date}); }
278 if ($details->{description}) { $trial->set_description($details->{description}); }
279 if ($details->{field_size}) { $trial->set_field_size($details->{field_size}); }
280 if ($details->{plot_width}) { $trial->set_plot_width($details->{plot_width}); }
281 if ($details->{plot_length}) { $trial->set_plot_length($details->{plot_length}); }
282 if ($details->{plan_to_genotype}) { $trial->set_field_trial_is_planned_to_be_genotyped($details->{plan_to_genotype}); }
283 if ($details->{plan_to_cross}) { $trial->set_field_trial_is_planned_to_cross($details->{plan_to_cross}); }
286 if ($details->{plate_format}) { $trial->set_genotyping_plate_format($details->{plate_format}); }
287 if ($details->{plate_sample_type}) { $trial->set_genotyping_plate_sample_type($details->{plate_sample_type}); }
288 if ($details->{facility}) { $trial->set_genotyping_facility($details->{facility}); }
289 if ($details->{facility_submitted}) { $trial->set_genotyping_facility_submitted($details->{facility_submitted}); }
290 if ($details->{facility_status}) { $trial->set_genotyping_facility_status($details->{set_genotyping_facility_status}); }
291 if ($details->{raw_data_link}) { $trial->set_raw_data_link($details->{raw_data_link}); }
293 if ($@) {
294 $c->stash->{rest} = { error => "An error occurred setting the new trial details: $@" };
296 else {
297 $c->stash->{rest} = { success => 1 };
301 sub traits_assayed : Chained('trial') PathPart('traits_assayed') Args(0) {
302 my $self = shift;
303 my $c = shift;
304 my $stock_type = $c->req->param('stock_type');
306 my @traits_assayed = $c->stash->{trial}->get_traits_assayed($stock_type);
307 $c->stash->{rest} = { traits_assayed => \@traits_assayed };
310 sub trait_phenotypes : Chained('trial') PathPart('trait_phenotypes') Args(0) {
311 my $self = shift;
312 my $c = shift;
313 my $start_date = shift;
314 my $end_date = shift;
315 my $include_dateless_items = shift;
317 #get userinfo from db
318 my $schema = $c->dbic_schema("Bio::Chado::Schema");
319 my $user = $c->user();
320 if (! $c->user) {
321 $c->stash->{rest} = {
322 status => "not logged in"
324 return;
326 my $display = $c->req->param('display');
327 my $trait = $c->req->param('trait');
328 my $phenotypes_search = CXGN::Phenotypes::PhenotypeMatrix->new(
329 bcs_schema=> $schema,
330 search_type => "Native",
331 data_level => $display,
332 trait_list=> [$trait],
333 trial_list => [$c->stash->{trial_id}],
334 start_date => $start_date,
335 end_date => $end_date,
336 include_dateless_items => $include_dateless_items,
338 my @data = $phenotypes_search->get_phenotype_matrix();
339 $c->stash->{rest} = {
340 status => "success",
341 data => \@data
345 sub phenotype_summary : Chained('trial') PathPart('phenotypes') Args(0) {
346 my $self = shift;
347 my $c = shift;
349 my $schema = $c->stash->{schema};
350 my $round = Math::Round::Var->new(0.01);
351 my $dbh = $c->dbc->dbh();
352 my $trial_id = $c->stash->{trial_id};
353 my $display = $c->req->param('display');
354 my $trial_stock_type = $c->req->param('trial_stock_type');
355 my $select_clause_additional = '';
356 my $group_by_additional = '';
357 my $order_by_additional = '';
358 my $stock_type_id;
359 my $rel_type_id;
360 my $total_complete_number;
361 if ($display eq 'plots') {
362 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot', 'stock_type')->cvterm_id();
363 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot_of', 'stock_relationship')->cvterm_id();
364 my $plots = $c->stash->{trial}->get_plots();
365 $total_complete_number = scalar (@$plots);
367 if ($display eq 'plants') {
368 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plant', 'stock_type')->cvterm_id();
369 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plant_of', 'stock_relationship')->cvterm_id();
370 my $plants = $c->stash->{trial}->get_plants();
371 $total_complete_number = scalar (@$plants);
373 if ($display eq 'subplots') {
374 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'subplot', 'stock_type')->cvterm_id();
375 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'subplot_of', 'stock_relationship')->cvterm_id();
376 my $subplots = $c->stash->{trial}->get_subplots();
377 $total_complete_number = scalar (@$subplots);
379 if ($display eq 'tissue_samples') {
380 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'tissue_sample', 'stock_type')->cvterm_id();
381 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'tissue_sample_of', 'stock_relationship')->cvterm_id();
382 my $subplots = $c->stash->{trial}->get_subplots();
383 $total_complete_number = scalar (@$subplots);
385 my $stocks_per_accession;
386 if ($display eq 'plots_accession') {
387 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot', 'stock_type')->cvterm_id();
388 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot_of', 'stock_relationship')->cvterm_id();
389 $select_clause_additional = ', accession.uniquename, accession.stock_id';
390 $group_by_additional = ', accession.stock_id, accession.uniquename';
391 $stocks_per_accession = $c->stash->{trial}->get_plots_per_accession();
392 $order_by_additional = ' ,accession.uniquename DESC';
394 if ($display eq 'plants_accession') {
395 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plant', 'stock_type')->cvterm_id();
396 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plant_of', 'stock_relationship')->cvterm_id();
397 $select_clause_additional = ', accession.uniquename, accession.stock_id';
398 $group_by_additional = ', accession.stock_id, accession.uniquename';
399 $stocks_per_accession = $c->stash->{trial}->get_plants_per_accession();
400 $order_by_additional = ' ,accession.uniquename DESC';
402 if ($display eq 'tissue_samples_accession') {
403 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'tissue_sample', 'stock_type')->cvterm_id();
404 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'tissue_sample_of', 'stock_relationship')->cvterm_id();
405 $select_clause_additional = ', accession.uniquename, accession.stock_id';
406 $group_by_additional = ', accession.stock_id, accession.uniquename';
407 $stocks_per_accession = $c->stash->{trial}->get_plants_per_accession();
408 $order_by_additional = ' ,accession.uniquename DESC';
410 if ($display eq 'analysis_instance') {
411 $stock_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'analysis_instance', 'stock_type')->cvterm_id();
412 $rel_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'analysis_of', 'stock_relationship')->cvterm_id();
413 # my $plots = $c->stash->{trial}->get_plots();
414 # $total_complete_number = scalar (@$plots);
416 my $accesion_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'accession', 'stock_type')->cvterm_id();
417 my $family_name_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'family_name', 'stock_type')->cvterm_id();
418 my $cross_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'cross', 'stock_type')->cvterm_id();
419 my $trial_stock_type_id;
420 if ($trial_stock_type eq 'family_name') {
421 $trial_stock_type_id = $family_name_type_id;
422 } elsif ($trial_stock_type eq 'cross') {
423 $trial_stock_type_id = $cross_type_id;
424 } else {
425 $trial_stock_type_id = $accesion_type_id;
428 my $h = $dbh->prepare("SELECT (((cvterm.name::text || '|'::text) || db.name::text) || ':'::text) || dbxref.accession::text AS trait,
429 cvterm.cvterm_id,
430 count(phenotype.value),
431 to_char(avg(phenotype.value::real), 'FM999990.990'),
432 to_char(max(phenotype.value::real), 'FM999990.990'),
433 to_char(min(phenotype.value::real), 'FM999990.990'),
434 to_char(stddev(phenotype.value::real), 'FM999990.990')
435 $select_clause_additional
436 FROM cvterm
437 JOIN phenotype ON (cvterm_id=cvalue_id)
438 JOIN nd_experiment_phenotype USING(phenotype_id)
439 JOIN nd_experiment_project USING(nd_experiment_id)
440 JOIN nd_experiment_stock USING(nd_experiment_id)
441 JOIN stock as plot USING(stock_id)
442 JOIN stock_relationship on (plot.stock_id = stock_relationship.subject_id)
443 JOIN stock as accession on (accession.stock_id = stock_relationship.object_id)
444 JOIN dbxref ON cvterm.dbxref_id = dbxref.dbxref_id JOIN db ON dbxref.db_id = db.db_id
445 WHERE project_id=?
446 AND phenotype.value~?
447 AND stock_relationship.type_id=?
448 AND plot.type_id=?
449 AND accession.type_id=?
450 GROUP BY (((cvterm.name::text || '|'::text) || db.name::text) || ':'::text) || dbxref.accession::text, cvterm.cvterm_id $group_by_additional
451 ORDER BY cvterm.name ASC
452 $order_by_additional;");
454 my $numeric_regex = '^-?[0-9]+([,.][0-9]+)?$';
455 $h->execute($c->stash->{trial_id}, $numeric_regex, $rel_type_id, $stock_type_id, $trial_stock_type_id);
457 my @phenotype_data;
459 while (my ($trait, $trait_id, $count, $average, $max, $min, $stddev, $stock_name, $stock_id) = $h->fetchrow_array()) {
461 my $cv = 0;
462 if ($stddev && $average != 0) {
463 $cv = ($stddev / $average) * 100;
464 $cv = $round->round($cv) . '%';
466 if ($average) { $average = $round->round($average); }
467 if ($min) { $min = $round->round($min); }
468 if ($max) { $max = $round->round($max); }
469 if ($stddev) { $stddev = $round->round($stddev); }
471 my @return_array;
472 if ($stock_name && $stock_id) {
473 $total_complete_number = scalar (@{$stocks_per_accession->{$stock_id}});
474 push @return_array, qq{<a href="/stock/$stock_id/view">$stock_name</a>};
476 my $percent_missing = '';
477 if ($total_complete_number > $count){
478 $percent_missing = sprintf("%.2f", 100 -(($count/$total_complete_number)*100))."%";
479 } else {
480 $percent_missing = "0%";
483 push @return_array, ( qq{<a href="/cvterm/$trait_id/view">$trait</a>}, $average, $min, $max, $stddev, $cv, $count, $percent_missing, qq{<a href="#raw_data_histogram_well" onclick="trait_summary_hist_change($trait_id)"><span class="glyphicon glyphicon-stats"></span></a>} );
484 push @phenotype_data, \@return_array;
487 $c->stash->{rest} = { data => \@phenotype_data };
490 sub trait_histogram : Chained('trial') PathPart('trait_histogram') Args(1) {
491 my $self = shift;
492 my $c = shift;
493 my $trait_id = shift;
494 my $stock_type = $c->req->param('stock_type') || 'plot';
496 my @data = $c->stash->{trial}->get_phenotypes_for_trait($trait_id, $stock_type);
498 $c->stash->{rest} = { data => \@data };
501 sub get_trial_folder :Chained('trial') PathPart('folder') Args(0) {
502 my $self = shift;
503 my $c = shift;
505 if (!($c->user()->check_roles('curator') || $c->user()->check_roles('submitter'))) {
506 $c->stash->{rest} = { error => 'You do not have the required privileges to edit the trial type of this trial.' };
507 return;
510 my $project_parent = $c->stash->{trial}->get_folder();
512 $c->stash->{rest} = { folder => [ $project_parent->project_id(), $project_parent->name() ] };
516 sub get_trial_location :Chained('trial') PathPart('location') Args(0) {
517 my $self = shift;
518 my $c = shift;
519 my $location = $c->stash->{trial}->get_location;
520 $c->stash->{rest} = { location => $location };
523 sub trial_accessions : Chained('trial') PathPart('accessions') Args(0) {
524 my $self = shift;
525 my $c = shift;
526 my $schema = $c->dbic_schema("Bio::Chado::Schema");
528 my $trial = CXGN::Trial->new( { bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
530 my @data = $trial->get_accessions();
532 $c->stash->{rest} = { accessions => \@data };
535 sub trial_stocks : Chained('trial') PathPart('stocks') Args(0) {
536 my $self = shift;
537 my $c = shift;
538 my $schema = $c->dbic_schema("Bio::Chado::Schema");
540 my $trial = CXGN::Trial->new( { bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
542 my $stocks = $trial->get_accessions();
544 $c->stash->{rest} = { data => $stocks };
547 sub trial_tissue_sources : Chained('trial') PathPart('tissue_sources') Args(0) {
548 my $self = shift;
549 my $c = shift;
550 my $schema = $c->dbic_schema("Bio::Chado::Schema");
552 my $trial = CXGN::Trial->new( { bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
553 my $data = $trial->get_tissue_sources();
554 #print STDERR Dumper $data;
555 $c->stash->{rest} = { tissue_sources => $data };
558 sub trial_seedlots : Chained('trial') PathPart('seedlots') Args(0) {
559 my $self = shift;
560 my $c = shift;
561 my $schema = $c->dbic_schema("Bio::Chado::Schema");
563 my $trial = CXGN::Trial->new( { bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
565 my @data = $trial->get_seedlots();
567 $c->stash->{rest} = { seedlots => \@data };
570 sub trial_used_seedlots_upload : Chained('trial') PathPart('upload_used_seedlots') Args(0) {
571 my $self = shift;
572 my $c = shift;
573 my $user_id;
574 my $user_name;
575 my $user_role;
576 my $session_id = $c->req->param("sgn_session_id");
578 if ($session_id){
579 my $dbh = $c->dbc->dbh;
580 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
581 if (!$user_info[0]){
582 $c->stash->{rest} = {error=>'You must be logged in to upload this seedlot info!'};
583 $c->detach();
585 $user_id = $user_info[0];
586 $user_role = $user_info[1];
587 my $p = CXGN::People::Person->new($dbh, $user_id);
588 $user_name = $p->get_username;
589 } else{
590 if (!$c->user){
591 $c->stash->{rest} = {error=>'You must be logged in to upload this seedlot info!'};
592 $c->detach();
594 $user_id = $c->user()->get_object()->get_sp_person_id();
595 $user_name = $c->user()->get_object()->get_username();
596 $user_role = $c->user->get_object->get_user_type();
599 my $schema = $c->dbic_schema("Bio::Chado::Schema");
600 my $upload = $c->req->upload('trial_upload_used_seedlot_file');
601 my $subdirectory = "trial_used_seedlot_upload";
602 my $upload_original_name = $upload->filename();
603 my $upload_tempfile = $upload->tempname;
604 my $time = DateTime->now();
605 my $timestamp = $time->ymd()."_".$time->hms();
607 ## Store uploaded temporary file in archive
608 my $uploader = CXGN::UploadFile->new({
609 tempfile => $upload_tempfile,
610 subdirectory => $subdirectory,
611 archive_path => $c->config->{archive_path},
612 archive_filename => $upload_original_name,
613 timestamp => $timestamp,
614 user_id => $user_id,
615 user_role => $user_role
617 my $archived_filename_with_path = $uploader->archive();
618 my $md5 = $uploader->get_md5($archived_filename_with_path);
619 if (!$archived_filename_with_path) {
620 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
621 $c->detach();
623 unlink $upload_tempfile;
624 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
625 $parser->load_plugin('TrialUsedSeedlotsXLS');
626 my $parsed_data = $parser->parse();
627 #print STDERR Dumper $parsed_data;
629 if (!$parsed_data) {
630 my $return_error = '';
631 my $parse_errors;
632 if (!$parser->has_parse_errors() ){
633 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
634 $c->detach();
635 } else {
636 $parse_errors = $parser->get_parse_errors();
637 #print STDERR Dumper $parse_errors;
639 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
640 $return_error .= $error_string."<br>";
643 $c->stash->{rest} = {error_string => $return_error, missing_seedlots => $parse_errors->{'missing_seedlots'}, missing_plots => $parse_errors->{'missing_plots'}};
644 $c->detach();
647 my $upload_used_seedlots_txn = sub {
648 while (my ($key, $val) = each(%$parsed_data)){
649 my $sl = CXGN::Stock::Seedlot->new(schema => $schema, seedlot_id => $val->{seedlot_stock_id});
651 my $transaction = CXGN::Stock::Seedlot::Transaction->new(schema => $schema);
652 $transaction->factor(1);
653 $transaction->from_stock([$val->{seedlot_stock_id}, $val->{seedlot_name}]);
654 $transaction->to_stock([$val->{plot_stock_id}, $val->{plot_name}]);
655 $transaction->amount($val->{amount});
656 $transaction->weight_gram($val->{weight_gram});
657 $transaction->timestamp($timestamp);
658 $transaction->description($val->{description});
659 $transaction->operator($user_name);
660 $transaction->store();
662 $sl->set_current_count_property();
663 $sl->set_current_weight_property();
665 my $layout = $c->stash->{trial_layout};
666 $layout->generate_and_cache_layout();
668 eval {
669 $schema->txn_do($upload_used_seedlots_txn);
671 if ($@) {
672 $c->stash->{rest} = { error => $@ };
673 print STDERR "An error condition occurred, was not able to upload trial used seedlots. ($@).\n";
674 $c->detach();
677 my $dbh = $c->dbc->dbh();
678 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
679 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
681 $c->stash->{rest} = { success => 1 };
684 sub trial_upload_plants : Chained('trial') PathPart('upload_plants') Args(0) {
685 my $self = shift;
686 my $c = shift;
687 my $user_id;
688 my $user_name;
689 my $user_role;
690 my $session_id = $c->req->param("sgn_session_id");
692 if ($session_id){
693 my $dbh = $c->dbc->dbh;
694 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
695 if (!$user_info[0]){
696 $c->stash->{rest} = {error=>'You must be logged in to upload this plants info!'};
697 $c->detach();
699 $user_id = $user_info[0];
700 $user_role = $user_info[1];
701 my $p = CXGN::People::Person->new($dbh, $user_id);
702 $user_name = $p->get_username;
703 } else{
704 if (!$c->user){
705 $c->stash->{rest} = {error=>'You must be logged in to upload this plants info!'};
706 $c->detach();
708 $user_id = $c->user()->get_object()->get_sp_person_id();
709 $user_name = $c->user()->get_object()->get_username();
710 $user_role = $c->user->get_object->get_user_type();
713 my $schema = $c->dbic_schema("Bio::Chado::Schema");
714 my $upload = $c->req->upload('trial_upload_plants_file');
715 my $inherits_plot_treatments = $c->req->param('upload_plants_per_plot_inherit_treatments');
716 my $plants_per_plot = $c->req->param('upload_plants_per_plot_number');
718 my $subdirectory = "trial_plants_upload";
719 my $upload_original_name = $upload->filename();
720 my $upload_tempfile = $upload->tempname;
721 my $time = DateTime->now();
722 my $timestamp = $time->ymd()."_".$time->hms();
724 ## Store uploaded temporary file in archive
725 my $uploader = CXGN::UploadFile->new({
726 tempfile => $upload_tempfile,
727 subdirectory => $subdirectory,
728 archive_path => $c->config->{archive_path},
729 archive_filename => $upload_original_name,
730 timestamp => $timestamp,
731 user_id => $user_id,
732 user_role => $user_role
734 my $archived_filename_with_path = $uploader->archive();
735 my $md5 = $uploader->get_md5($archived_filename_with_path);
736 if (!$archived_filename_with_path) {
737 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
738 $c->detach();
740 unlink $upload_tempfile;
741 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
742 $parser->load_plugin('TrialPlantsXLS');
743 my $parsed_data = $parser->parse();
744 #print STDERR Dumper $parsed_data;
746 if (!$parsed_data) {
747 my $return_error = '';
748 my $parse_errors;
749 if (!$parser->has_parse_errors() ){
750 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
751 $c->detach();
752 } else {
753 $parse_errors = $parser->get_parse_errors();
754 #print STDERR Dumper $parse_errors;
756 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
757 $return_error .= $error_string."<br>";
760 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
761 $c->detach();
764 my $upload_plants_txn = sub {
765 my %plot_plant_hash;
766 my $parsed_entries = $parsed_data->{data};
767 foreach (@$parsed_entries){
768 $plot_plant_hash{$_->{plot_stock_id}}->{plot_name} = $_->{plot_name};
769 push @{$plot_plant_hash{$_->{plot_stock_id}}->{plant_names}}, $_->{plant_name};
771 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
772 $t->save_plant_entries(\%plot_plant_hash, $plants_per_plot, $inherits_plot_treatments, $user_id);
774 my $layout = $c->stash->{trial_layout};
775 $layout->generate_and_cache_layout();
777 eval {
778 $schema->txn_do($upload_plants_txn);
780 if ($@) {
781 $c->stash->{rest} = { error => $@ };
782 print STDERR "An error condition occurred, was not able to upload trial plants. ($@).\n";
783 $c->detach();
786 my $dbh = $c->dbc->dbh();
787 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
788 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
790 $c->stash->{rest} = { success => 1 };
793 sub trial_upload_plants_subplot : Chained('trial') PathPart('upload_plants_subplot') Args(0) {
794 my $self = shift;
795 my $c = shift;
796 my $user_id;
797 my $user_name;
798 my $user_role;
799 my $session_id = $c->req->param("sgn_session_id");
801 if ($session_id){
802 my $dbh = $c->dbc->dbh;
803 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
804 if (!$user_info[0]){
805 $c->stash->{rest} = {error=>'You must be logged in to upload this plants info!'};
806 $c->detach();
808 $user_id = $user_info[0];
809 $user_role = $user_info[1];
810 my $p = CXGN::People::Person->new($dbh, $user_id);
811 $user_name = $p->get_username;
812 } else{
813 if (!$c->user){
814 $c->stash->{rest} = {error=>'You must be logged in to upload this plants info!'};
815 $c->detach();
817 $user_id = $c->user()->get_object()->get_sp_person_id();
818 $user_name = $c->user()->get_object()->get_username();
819 $user_role = $c->user->get_object->get_user_type();
822 my $schema = $c->dbic_schema("Bio::Chado::Schema");
823 my $upload = $c->req->upload('trial_upload_plants_subplot_file');
824 my $inherits_plot_treatments = $c->req->param('upload_plants_per_subplot_inherit_treatments');
825 my $plants_per_subplot = $c->req->param('upload_plants_per_subplot_number');
827 my $subdirectory = "trial_plants_upload";
828 my $upload_original_name = $upload->filename();
829 my $upload_tempfile = $upload->tempname;
830 my $time = DateTime->now();
831 my $timestamp = $time->ymd()."_".$time->hms();
833 ## Store uploaded temporary file in archive
834 my $uploader = CXGN::UploadFile->new({
835 tempfile => $upload_tempfile,
836 subdirectory => $subdirectory,
837 archive_path => $c->config->{archive_path},
838 archive_filename => $upload_original_name,
839 timestamp => $timestamp,
840 user_id => $user_id,
841 user_role => $user_role
843 my $archived_filename_with_path = $uploader->archive();
844 my $md5 = $uploader->get_md5($archived_filename_with_path);
845 if (!$archived_filename_with_path) {
846 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
847 $c->detach();
849 unlink $upload_tempfile;
850 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
851 $parser->load_plugin('TrialPlantsSubplotXLS');
852 my $parsed_data = $parser->parse();
853 #print STDERR Dumper $parsed_data;
855 if (!$parsed_data) {
856 my $return_error = '';
857 my $parse_errors;
858 if (!$parser->has_parse_errors() ){
859 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
860 $c->detach();
861 } else {
862 $parse_errors = $parser->get_parse_errors();
863 #print STDERR Dumper $parse_errors;
865 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
866 $return_error .= $error_string."<br>";
869 $c->stash->{rest} = {error_string => $return_error, missing_subplots => $parse_errors->{'missing_subplots'}};
870 $c->detach();
873 my $upload_plants_txn = sub {
874 my %subplot_plant_hash;
875 my $parsed_entries = $parsed_data->{data};
876 foreach (@$parsed_entries){
877 $subplot_plant_hash{$_->{subplot_stock_id}}->{subplot_name} = $_->{subplot_name};
878 push @{$subplot_plant_hash{$_->{subplot_stock_id}}->{plant_names}}, $_->{plant_name};
880 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
881 $t->save_plant_subplot_entries(\%subplot_plant_hash, $plants_per_subplot, $inherits_plot_treatments, $user_id);
883 my $layout = $c->stash->{trial_layout};
884 $layout->generate_and_cache_layout();
886 eval {
887 $schema->txn_do($upload_plants_txn);
889 if ($@) {
890 $c->stash->{rest} = { error => $@ };
891 print STDERR "An error condition occurred, was not able to upload trial plants. ($@).\n";
892 $c->detach();
895 my $dbh = $c->dbc->dbh();
896 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
897 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
899 $c->stash->{rest} = { success => 1 };
902 sub trial_upload_subplots : Chained('trial') PathPart('upload_subplots') Args(0) {
903 my $self = shift;
904 my $c = shift;
905 my $user_id;
906 my $user_name;
907 my $user_role;
908 my $session_id = $c->req->param("sgn_session_id");
910 if ($session_id){
911 my $dbh = $c->dbc->dbh;
912 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
913 if (!$user_info[0]){
914 $c->stash->{rest} = {error=>'You must be logged in to upload this subplots info!'};
915 $c->detach();
917 $user_id = $user_info[0];
918 $user_role = $user_info[1];
919 my $p = CXGN::People::Person->new($dbh, $user_id);
920 $user_name = $p->get_username;
921 } else{
922 if (!$c->user){
923 $c->stash->{rest} = {error=>'You must be logged in to upload this subplots info!'};
924 $c->detach();
926 $user_id = $c->user()->get_object()->get_sp_person_id();
927 $user_name = $c->user()->get_object()->get_username();
928 $user_role = $c->user->get_object->get_user_type();
931 my $schema = $c->dbic_schema("Bio::Chado::Schema");
932 my $upload = $c->req->upload('trial_upload_subplots_file');
933 my $inherits_plot_treatments = $c->req->param('upload_subplots_per_plot_inherit_treatments');
934 my $subplots_per_plot = $c->req->param('upload_subplots_per_plot_number');
936 my $subdirectory = "trial_subplots_upload";
937 my $upload_original_name = $upload->filename();
938 my $upload_tempfile = $upload->tempname;
939 my $time = DateTime->now();
940 my $timestamp = $time->ymd()."_".$time->hms();
942 ## Store uploaded temporary file in archive
943 my $uploader = CXGN::UploadFile->new({
944 tempfile => $upload_tempfile,
945 subdirectory => $subdirectory,
946 archive_path => $c->config->{archive_path},
947 archive_filename => $upload_original_name,
948 timestamp => $timestamp,
949 user_id => $user_id,
950 user_role => $user_role
952 my $archived_filename_with_path = $uploader->archive();
953 my $md5 = $uploader->get_md5($archived_filename_with_path);
954 if (!$archived_filename_with_path) {
955 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
956 $c->detach();
958 unlink $upload_tempfile;
959 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
960 $parser->load_plugin('TrialSubplotsXLS');
961 my $parsed_data = $parser->parse();
962 #print STDERR Dumper $parsed_data;
964 if (!$parsed_data) {
965 my $return_error = '';
966 my $parse_errors;
967 if (!$parser->has_parse_errors() ){
968 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
969 $c->detach();
970 } else {
971 $parse_errors = $parser->get_parse_errors();
972 #print STDERR Dumper $parse_errors;
974 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
975 $return_error .= $error_string."<br>";
978 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
979 $c->detach();
982 my $upload_subplots_txn = sub {
983 my %plot_subplot_hash;
984 my $parsed_entries = $parsed_data->{data};
985 foreach (@$parsed_entries){
986 $plot_subplot_hash{$_->{plot_stock_id}}->{plot_name} = $_->{plot_name};
987 push @{$plot_subplot_hash{$_->{plot_stock_id}}->{subplot_names}}, $_->{subplot_name};
989 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
990 $t->save_subplot_entries(\%plot_subplot_hash, $subplots_per_plot, $inherits_plot_treatments, $user_id);
992 my $layout = $c->stash->{trial_layout};
993 $layout->generate_and_cache_layout();
995 eval {
996 $schema->txn_do($upload_subplots_txn);
998 if ($@) {
999 $c->stash->{rest} = { error => $@ };
1000 print STDERR "An error condition occurred, was not able to upload trial subplots. ($@).\n";
1001 $c->detach();
1004 my $dbh = $c->dbc->dbh();
1005 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1006 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1008 $c->stash->{rest} = { success => 1 };
1011 sub trial_upload_plants_with_index_number : Chained('trial') PathPart('upload_plants_with_plant_index_number') Args(0) {
1012 my $self = shift;
1013 my $c = shift;
1014 my $user_id;
1015 my $user_name;
1016 my $user_role;
1017 my $session_id = $c->req->param("sgn_session_id");
1019 if ($session_id){
1020 my $dbh = $c->dbc->dbh;
1021 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1022 if (!$user_info[0]){
1023 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1024 $c->detach();
1026 $user_id = $user_info[0];
1027 $user_role = $user_info[1];
1028 my $p = CXGN::People::Person->new($dbh, $user_id);
1029 $user_name = $p->get_username;
1030 } else{
1031 if (!$c->user){
1032 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1033 $c->detach();
1035 $user_id = $c->user()->get_object()->get_sp_person_id();
1036 $user_name = $c->user()->get_object()->get_username();
1037 $user_role = $c->user->get_object->get_user_type();
1040 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1041 my $upload = $c->req->upload('trial_upload_plants_with_index_number_file');
1042 my $inherits_plot_treatments = $c->req->param('upload_plants_with_index_number_inherit_treatments');
1043 my $plants_per_plot = $c->req->param('upload_plants_with_index_number_per_plot_number');
1045 my $subdirectory = "trial_plants_upload";
1046 my $upload_original_name = $upload->filename();
1047 my $upload_tempfile = $upload->tempname;
1048 my $time = DateTime->now();
1049 my $timestamp = $time->ymd()."_".$time->hms();
1051 ## Store uploaded temporary file in archive
1052 my $uploader = CXGN::UploadFile->new({
1053 tempfile => $upload_tempfile,
1054 subdirectory => $subdirectory,
1055 archive_path => $c->config->{archive_path},
1056 archive_filename => $upload_original_name,
1057 timestamp => $timestamp,
1058 user_id => $user_id,
1059 user_role => $user_role
1061 my $archived_filename_with_path = $uploader->archive();
1062 my $md5 = $uploader->get_md5($archived_filename_with_path);
1063 if (!$archived_filename_with_path) {
1064 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1065 $c->detach();
1067 unlink $upload_tempfile;
1068 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1069 $parser->load_plugin('TrialPlantsWithPlantNumberXLS');
1070 my $parsed_data = $parser->parse();
1071 #print STDERR Dumper $parsed_data;
1073 if (!$parsed_data) {
1074 my $return_error = '';
1075 my $parse_errors;
1076 if (!$parser->has_parse_errors() ){
1077 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1078 $c->detach();
1079 } else {
1080 $parse_errors = $parser->get_parse_errors();
1081 #print STDERR Dumper $parse_errors;
1083 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1084 $return_error .= $error_string."<br>";
1087 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
1088 $c->detach();
1091 my $upload_plants_txn = sub {
1092 my %plot_plant_hash;
1093 my $parsed_entries = $parsed_data->{data};
1094 foreach (@$parsed_entries){
1095 $plot_plant_hash{$_->{plot_stock_id}}->{plot_name} = $_->{plot_name};
1096 push @{$plot_plant_hash{$_->{plot_stock_id}}->{plant_names}}, $_->{plant_name};
1097 push @{$plot_plant_hash{$_->{plot_stock_id}}->{plant_index_numbers}}, $_->{plant_index_number};
1099 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
1100 $t->save_plant_entries(\%plot_plant_hash, $plants_per_plot, $inherits_plot_treatments, $user_id);
1102 my $layout = $c->stash->{trial_layout};
1103 $layout->generate_and_cache_layout();
1105 eval {
1106 $schema->txn_do($upload_plants_txn);
1108 if ($@) {
1109 $c->stash->{rest} = { error => $@ };
1110 print STDERR "An error condition occurred, was not able to upload trial plants. ($@).\n";
1111 $c->detach();
1114 my $dbh = $c->dbc->dbh();
1115 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1116 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1118 $c->stash->{rest} = { success => 1 };
1121 sub trial_upload_plants_subplot_with_index_number : Chained('trial') PathPart('upload_plants_subplot_with_plant_index_number') Args(0) {
1122 my $self = shift;
1123 my $c = shift;
1124 my $user_id;
1125 my $user_name;
1126 my $user_role;
1127 my $session_id = $c->req->param("sgn_session_id");
1129 if ($session_id){
1130 my $dbh = $c->dbc->dbh;
1131 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1132 if (!$user_info[0]){
1133 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1134 $c->detach();
1136 $user_id = $user_info[0];
1137 $user_role = $user_info[1];
1138 my $p = CXGN::People::Person->new($dbh, $user_id);
1139 $user_name = $p->get_username;
1140 } else{
1141 if (!$c->user){
1142 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1143 $c->detach();
1145 $user_id = $c->user()->get_object()->get_sp_person_id();
1146 $user_name = $c->user()->get_object()->get_username();
1147 $user_role = $c->user->get_object->get_user_type();
1150 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1151 my $upload = $c->req->upload('trial_upload_plants_subplot_with_index_number_file');
1152 my $inherits_plot_treatments = $c->req->param('upload_plants_subplot_with_index_number_inherit_treatments');
1153 my $plants_per_subplot = $c->req->param('upload_plants_subplot_with_index_number_per_subplot_number');
1155 my $subdirectory = "trial_plants_upload";
1156 my $upload_original_name = $upload->filename();
1157 my $upload_tempfile = $upload->tempname;
1158 my $time = DateTime->now();
1159 my $timestamp = $time->ymd()."_".$time->hms();
1161 ## Store uploaded temporary file in archive
1162 my $uploader = CXGN::UploadFile->new({
1163 tempfile => $upload_tempfile,
1164 subdirectory => $subdirectory,
1165 archive_path => $c->config->{archive_path},
1166 archive_filename => $upload_original_name,
1167 timestamp => $timestamp,
1168 user_id => $user_id,
1169 user_role => $user_role
1171 my $archived_filename_with_path = $uploader->archive();
1172 my $md5 = $uploader->get_md5($archived_filename_with_path);
1173 if (!$archived_filename_with_path) {
1174 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1175 $c->detach();
1177 unlink $upload_tempfile;
1178 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1179 $parser->load_plugin('TrialPlantsSubplotWithPlantNumberXLS');
1180 my $parsed_data = $parser->parse();
1181 #print STDERR Dumper $parsed_data;
1183 if (!$parsed_data) {
1184 my $return_error = '';
1185 my $parse_errors;
1186 if (!$parser->has_parse_errors() ){
1187 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1188 $c->detach();
1189 } else {
1190 $parse_errors = $parser->get_parse_errors();
1191 #print STDERR Dumper $parse_errors;
1193 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1194 $return_error .= $error_string."<br>";
1197 $c->stash->{rest} = {error_string => $return_error, missing_subplots => $parse_errors->{'missing_subplots'}};
1198 $c->detach();
1201 my $upload_plants_txn = sub {
1202 my %subplot_plant_hash;
1203 my $parsed_entries = $parsed_data->{data};
1204 foreach (@$parsed_entries){
1205 $subplot_plant_hash{$_->{subplot_stock_id}}->{subplot_name} = $_->{subplot_name};
1206 push @{$subplot_plant_hash{$_->{subplot_stock_id}}->{plant_names}}, $_->{plant_name};
1207 push @{$subplot_plant_hash{$_->{subplot_stock_id}}->{plant_index_numbers}}, $_->{plant_index_number};
1209 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
1210 $t->save_plant_subplot_entries(\%subplot_plant_hash, $plants_per_subplot, $inherits_plot_treatments, $user_id);
1212 my $layout = $c->stash->{trial_layout};
1213 $layout->generate_and_cache_layout();
1215 eval {
1216 $schema->txn_do($upload_plants_txn);
1218 if ($@) {
1219 $c->stash->{rest} = { error => $@ };
1220 print STDERR "An error condition occurred, was not able to upload trial plants. ($@).\n";
1221 $c->detach();
1224 my $dbh = $c->dbc->dbh();
1225 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1226 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1228 $c->stash->{rest} = { success => 1 };
1231 sub trial_upload_subplots_with_index_number : Chained('trial') PathPart('upload_subplots_with_subplot_index_number') Args(0) {
1232 my $self = shift;
1233 my $c = shift;
1234 my $user_id;
1235 my $user_name;
1236 my $user_role;
1237 my $session_id = $c->req->param("sgn_session_id");
1239 if ($session_id){
1240 my $dbh = $c->dbc->dbh;
1241 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1242 if (!$user_info[0]){
1243 $c->stash->{rest} = {error=>'You must be logged in to upload this subplot info!'};
1244 $c->detach();
1246 $user_id = $user_info[0];
1247 $user_role = $user_info[1];
1248 my $p = CXGN::People::Person->new($dbh, $user_id);
1249 $user_name = $p->get_username;
1250 } else{
1251 if (!$c->user){
1252 $c->stash->{rest} = {error=>'You must be logged in to upload this subplot info!'};
1253 $c->detach();
1255 $user_id = $c->user()->get_object()->get_sp_person_id();
1256 $user_name = $c->user()->get_object()->get_username();
1257 $user_role = $c->user->get_object->get_user_type();
1260 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1261 my $upload = $c->req->upload('trial_upload_subplots_with_index_number_file');
1262 my $inherits_plot_treatments = $c->req->param('upload_subplots_with_index_number_inherit_treatments');
1263 my $subplots_per_plot = $c->req->param('upload_subplots_with_index_number_per_plot_number');
1265 my $subdirectory = "trial_subplots_upload";
1266 my $upload_original_name = $upload->filename();
1267 my $upload_tempfile = $upload->tempname;
1268 my $time = DateTime->now();
1269 my $timestamp = $time->ymd()."_".$time->hms();
1271 ## Store uploaded temporary file in archive
1272 my $uploader = CXGN::UploadFile->new({
1273 tempfile => $upload_tempfile,
1274 subdirectory => $subdirectory,
1275 archive_path => $c->config->{archive_path},
1276 archive_filename => $upload_original_name,
1277 timestamp => $timestamp,
1278 user_id => $user_id,
1279 user_role => $user_role
1281 my $archived_filename_with_path = $uploader->archive();
1282 my $md5 = $uploader->get_md5($archived_filename_with_path);
1283 if (!$archived_filename_with_path) {
1284 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1285 $c->detach();
1287 unlink $upload_tempfile;
1288 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1289 $parser->load_plugin('TrialSubplotsWithSubplotNumberXLS');
1290 my $parsed_data = $parser->parse();
1291 #print STDERR Dumper $parsed_data;
1293 if (!$parsed_data) {
1294 my $return_error = '';
1295 my $parse_errors;
1296 if (!$parser->has_parse_errors() ){
1297 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1298 $c->detach();
1299 } else {
1300 $parse_errors = $parser->get_parse_errors();
1301 #print STDERR Dumper $parse_errors;
1303 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1304 $return_error .= $error_string."<br>";
1307 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
1308 $c->detach();
1311 my $upload_subplots_txn = sub {
1312 my %plot_subplot_hash;
1313 my $parsed_entries = $parsed_data->{data};
1314 foreach (@$parsed_entries){
1315 $plot_subplot_hash{$_->{plot_stock_id}}->{plot_name} = $_->{plot_name};
1316 push @{$plot_subplot_hash{$_->{plot_stock_id}}->{subplot_names}}, $_->{subplot_name};
1317 push @{$plot_subplot_hash{$_->{plot_stock_id}}->{subplot_index_numbers}}, $_->{subplot_index_number};
1319 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
1320 $t->save_subplot_entries(\%plot_subplot_hash, $subplots_per_plot, $inherits_plot_treatments, $user_id);
1322 my $layout = $c->stash->{trial_layout};
1323 $layout->generate_and_cache_layout();
1325 eval {
1326 $schema->txn_do($upload_subplots_txn);
1328 if ($@) {
1329 $c->stash->{rest} = { error => $@ };
1330 print STDERR "An error condition occurred, was not able to upload trial subplots. ($@).\n";
1331 $c->detach();
1334 my $dbh = $c->dbc->dbh();
1335 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1336 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1338 $c->stash->{rest} = { success => 1 };
1341 sub trial_upload_plants_with_number_of_plants : Chained('trial') PathPart('upload_plants_with_number_of_plants') Args(0) {
1342 my $self = shift;
1343 my $c = shift;
1344 my $user_id;
1345 my $user_name;
1346 my $user_role;
1347 my $session_id = $c->req->param("sgn_session_id");
1349 if ($session_id){
1350 my $dbh = $c->dbc->dbh;
1351 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1352 if (!$user_info[0]){
1353 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1354 $c->detach();
1356 $user_id = $user_info[0];
1357 $user_role = $user_info[1];
1358 my $p = CXGN::People::Person->new($dbh, $user_id);
1359 $user_name = $p->get_username;
1360 } else{
1361 if (!$c->user){
1362 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1363 $c->detach();
1365 $user_id = $c->user()->get_object()->get_sp_person_id();
1366 $user_name = $c->user()->get_object()->get_username();
1367 $user_role = $c->user->get_object->get_user_type();
1370 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1371 my $upload = $c->req->upload('trial_upload_plants_with_number_of_plants_file');
1372 my $inherits_plot_treatments = $c->req->param('upload_plants_with_num_plants_inherit_treatments');
1373 my $plants_per_plot = $c->req->param('upload_plants_with_num_plants_per_plot_number');
1375 my $subdirectory = "trial_plants_upload";
1376 my $upload_original_name = $upload->filename();
1377 my $upload_tempfile = $upload->tempname;
1378 my $time = DateTime->now();
1379 my $timestamp = $time->ymd()."_".$time->hms();
1381 ## Store uploaded temporary file in archive
1382 my $uploader = CXGN::UploadFile->new({
1383 tempfile => $upload_tempfile,
1384 subdirectory => $subdirectory,
1385 archive_path => $c->config->{archive_path},
1386 archive_filename => $upload_original_name,
1387 timestamp => $timestamp,
1388 user_id => $user_id,
1389 user_role => $user_role
1391 my $archived_filename_with_path = $uploader->archive();
1392 my $md5 = $uploader->get_md5($archived_filename_with_path);
1393 if (!$archived_filename_with_path) {
1394 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1395 $c->detach();
1397 unlink $upload_tempfile;
1398 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1399 $parser->load_plugin('TrialPlantsWithNumberOfPlantsXLS');
1400 my $parsed_data = $parser->parse();
1401 #print STDERR Dumper $parsed_data;
1403 if (!$parsed_data) {
1404 my $return_error = '';
1405 my $parse_errors;
1406 if (!$parser->has_parse_errors() ){
1407 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1408 $c->detach();
1409 } else {
1410 $parse_errors = $parser->get_parse_errors();
1411 #print STDERR Dumper $parse_errors;
1413 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1414 $return_error .= $error_string."<br>";
1417 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
1418 $c->detach();
1421 my $upload_plants_txn = sub {
1422 my %plot_plant_hash;
1423 my $parsed_entries = $parsed_data->{data};
1424 foreach (@$parsed_entries){
1425 $plot_plant_hash{$_->{plot_stock_id}}->{plot_name} = $_->{plot_name};
1426 push @{$plot_plant_hash{$_->{plot_stock_id}}->{plant_names}}, $_->{plant_name};
1427 push @{$plot_plant_hash{$_->{plot_stock_id}}->{plant_index_numbers}}, $_->{plant_index_number};
1429 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
1430 $t->save_plant_entries(\%plot_plant_hash, $plants_per_plot, $inherits_plot_treatments, $user_id);
1432 my $layout = $c->stash->{trial_layout};
1433 $layout->generate_and_cache_layout();
1435 eval {
1436 $schema->txn_do($upload_plants_txn);
1438 if ($@) {
1439 $c->stash->{rest} = { error => $@ };
1440 print STDERR "An error condition occurred, was not able to upload trial plants. ($@).\n";
1441 $c->detach();
1444 my $dbh = $c->dbc->dbh();
1445 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1446 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1448 $c->stash->{rest} = { success => 1 };
1451 sub trial_upload_plants_subplot_with_number_of_plants : Chained('trial') PathPart('upload_plants_subplot_with_number_of_plants') Args(0) {
1452 my $self = shift;
1453 my $c = shift;
1454 my $user_id;
1455 my $user_name;
1456 my $user_role;
1457 my $session_id = $c->req->param("sgn_session_id");
1459 if ($session_id){
1460 my $dbh = $c->dbc->dbh;
1461 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1462 if (!$user_info[0]){
1463 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1464 $c->detach();
1466 $user_id = $user_info[0];
1467 $user_role = $user_info[1];
1468 my $p = CXGN::People::Person->new($dbh, $user_id);
1469 $user_name = $p->get_username;
1470 } else{
1471 if (!$c->user){
1472 $c->stash->{rest} = {error=>'You must be logged in to upload this plant info!'};
1473 $c->detach();
1475 $user_id = $c->user()->get_object()->get_sp_person_id();
1476 $user_name = $c->user()->get_object()->get_username();
1477 $user_role = $c->user->get_object->get_user_type();
1480 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1481 my $upload = $c->req->upload('trial_upload_plants_subplot_with_number_of_plants_file');
1482 my $inherits_plot_treatments = $c->req->param('upload_plants_subplot_with_num_plants_inherit_treatments');
1483 my $plants_per_subplot = $c->req->param('upload_plants_subplot_with_num_plants_per_subplot_number');
1485 my $subdirectory = "trial_plants_upload";
1486 my $upload_original_name = $upload->filename();
1487 my $upload_tempfile = $upload->tempname;
1488 my $time = DateTime->now();
1489 my $timestamp = $time->ymd()."_".$time->hms();
1491 ## Store uploaded temporary file in archive
1492 my $uploader = CXGN::UploadFile->new({
1493 tempfile => $upload_tempfile,
1494 subdirectory => $subdirectory,
1495 archive_path => $c->config->{archive_path},
1496 archive_filename => $upload_original_name,
1497 timestamp => $timestamp,
1498 user_id => $user_id,
1499 user_role => $user_role
1501 my $archived_filename_with_path = $uploader->archive();
1502 my $md5 = $uploader->get_md5($archived_filename_with_path);
1503 if (!$archived_filename_with_path) {
1504 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1505 $c->detach();
1507 unlink $upload_tempfile;
1508 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1509 $parser->load_plugin('TrialPlantsSubplotWithNumberOfPlantsXLS');
1510 my $parsed_data = $parser->parse();
1511 #print STDERR Dumper $parsed_data;
1513 if (!$parsed_data) {
1514 my $return_error = '';
1515 my $parse_errors;
1516 if (!$parser->has_parse_errors() ){
1517 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1518 $c->detach();
1519 } else {
1520 $parse_errors = $parser->get_parse_errors();
1521 #print STDERR Dumper $parse_errors;
1523 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1524 $return_error .= $error_string."<br>";
1527 $c->stash->{rest} = {error_string => $return_error, missing_subplots => $parse_errors->{'missing_subplots'}};
1528 $c->detach();
1531 my $upload_plants_txn = sub {
1532 my %subplot_plant_hash;
1533 my $parsed_entries = $parsed_data->{data};
1534 foreach (@$parsed_entries){
1535 $subplot_plant_hash{$_->{subplot_stock_id}}->{subplot_name} = $_->{subplot_name};
1536 push @{$subplot_plant_hash{$_->{subplot_stock_id}}->{plant_names}}, $_->{plant_name};
1537 push @{$subplot_plant_hash{$_->{subplot_stock_id}}->{plant_index_numbers}}, $_->{plant_index_number};
1539 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
1540 $t->save_plant_subplot_entries(\%subplot_plant_hash, $plants_per_subplot, $inherits_plot_treatments, $user_id);
1542 my $layout = $c->stash->{trial_layout};
1543 $layout->generate_and_cache_layout();
1545 eval {
1546 $schema->txn_do($upload_plants_txn);
1548 if ($@) {
1549 $c->stash->{rest} = { error => $@ };
1550 print STDERR "An error condition occurred, was not able to upload trial plants. ($@).\n";
1551 $c->detach();
1554 my $dbh = $c->dbc->dbh();
1555 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1556 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1558 $c->stash->{rest} = { success => 1 };
1561 sub trial_upload_subplots_with_number_of_subplots : Chained('trial') PathPart('upload_subplots_with_number_of_subplots') Args(0) {
1562 my $self = shift;
1563 my $c = shift;
1564 my $user_id;
1565 my $user_name;
1566 my $user_role;
1567 my $session_id = $c->req->param("sgn_session_id");
1569 if ($session_id){
1570 my $dbh = $c->dbc->dbh;
1571 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1572 if (!$user_info[0]){
1573 $c->stash->{rest} = {error=>'You must be logged in to upload this subplot info!'};
1574 $c->detach();
1576 $user_id = $user_info[0];
1577 $user_role = $user_info[1];
1578 my $p = CXGN::People::Person->new($dbh, $user_id);
1579 $user_name = $p->get_username;
1580 } else{
1581 if (!$c->user){
1582 $c->stash->{rest} = {error=>'You must be logged in to upload this subplot info!'};
1583 $c->detach();
1585 $user_id = $c->user()->get_object()->get_sp_person_id();
1586 $user_name = $c->user()->get_object()->get_username();
1587 $user_role = $c->user->get_object->get_user_type();
1590 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1591 my $upload = $c->req->upload('trial_upload_subplots_with_number_of_subplots_file');
1592 my $inherits_plot_treatments = $c->req->param('upload_subplots_with_num_subplots_inherit_treatments');
1593 my $subplots_per_plot = $c->req->param('upload_subplots_with_num_subplots_per_plot_number');
1595 my $subdirectory = "trial_subplots_upload";
1596 my $upload_original_name = $upload->filename();
1597 my $upload_tempfile = $upload->tempname;
1598 my $time = DateTime->now();
1599 my $timestamp = $time->ymd()."_".$time->hms();
1601 ## Store uploaded temporary file in archive
1602 my $uploader = CXGN::UploadFile->new({
1603 tempfile => $upload_tempfile,
1604 subdirectory => $subdirectory,
1605 archive_path => $c->config->{archive_path},
1606 archive_filename => $upload_original_name,
1607 timestamp => $timestamp,
1608 user_id => $user_id,
1609 user_role => $user_role
1611 my $archived_filename_with_path = $uploader->archive();
1612 my $md5 = $uploader->get_md5($archived_filename_with_path);
1613 if (!$archived_filename_with_path) {
1614 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1615 $c->detach();
1617 unlink $upload_tempfile;
1618 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1619 $parser->load_plugin('TrialSubplotsWithNumberOfSubplotsXLS');
1620 my $parsed_data = $parser->parse();
1621 #print STDERR Dumper $parsed_data;
1623 if (!$parsed_data) {
1624 my $return_error = '';
1625 my $parse_errors;
1626 if (!$parser->has_parse_errors() ){
1627 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1628 $c->detach();
1629 } else {
1630 $parse_errors = $parser->get_parse_errors();
1631 #print STDERR Dumper $parse_errors;
1633 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1634 $return_error .= $error_string."<br>";
1637 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
1638 $c->detach();
1641 my $upload_subplots_txn = sub {
1642 my %plot_subplot_hash;
1643 my $parsed_entries = $parsed_data->{data};
1644 foreach (@$parsed_entries){
1645 $plot_subplot_hash{$_->{plot_stock_id}}->{plot_name} = $_->{plot_name};
1646 push @{$plot_subplot_hash{$_->{plot_stock_id}}->{subplot_names}}, $_->{subplot_name};
1647 push @{$plot_subplot_hash{$_->{plot_stock_id}}->{subplot_index_numbers}}, $_->{subplot_index_number};
1649 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
1650 $t->save_subplot_entries(\%plot_subplot_hash, $subplots_per_plot, $inherits_plot_treatments, $user_id);
1652 my $layout = $c->stash->{trial_layout};
1653 $layout->generate_and_cache_layout();
1655 eval {
1656 $schema->txn_do($upload_subplots_txn);
1658 if ($@) {
1659 $c->stash->{rest} = { error => $@ };
1660 print STDERR "An error condition occurred, was not able to upload trial subplots. ($@).\n";
1661 $c->detach();
1664 my $dbh = $c->dbc->dbh();
1665 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1666 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1668 $c->stash->{rest} = { success => 1 };
1671 sub trial_plot_gps_upload : Chained('trial') PathPart('upload_plot_gps') Args(0) {
1672 my $self = shift;
1673 my $c = shift;
1674 my $user_id;
1675 my $user_name;
1676 my $user_role;
1677 my $session_id = $c->req->param("sgn_session_id");
1679 if ($session_id){
1680 my $dbh = $c->dbc->dbh;
1681 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1682 if (!$user_info[0]){
1683 $c->stash->{rest} = {error=>'You must be logged in to upload this seedlot info!'};
1684 $c->detach();
1686 $user_id = $user_info[0];
1687 $user_role = $user_info[1];
1688 my $p = CXGN::People::Person->new($dbh, $user_id);
1689 $user_name = $p->get_username;
1690 } else{
1691 if (!$c->user){
1692 $c->stash->{rest} = {error=>'You must be logged in to upload this seedlot info!'};
1693 $c->detach();
1695 $user_id = $c->user()->get_object()->get_sp_person_id();
1696 $user_name = $c->user()->get_object()->get_username();
1697 $user_role = $c->user->get_object->get_user_type();
1700 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1702 #Check that trial has a location set
1703 my $field_experiment_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'field_layout', 'experiment_type')->cvterm_id();
1704 my $nd_geolocation_rs = $schema->resultset('NaturalDiversity::NdGeolocation')->search(
1705 {'nd_experiments.type_id'=>$field_experiment_cvterm_id, 'project.project_id'=>$c->stash->{trial_id}},
1706 { 'join' => { 'nd_experiments' => {'nd_experiment_projects'=>'project'} } }
1708 my $nd_geolocation = $nd_geolocation_rs->first;
1709 if (!$nd_geolocation){
1710 $c->stash->{rest} = {error=>'This trial has no location set!'};
1711 $c->detach();
1714 my $upload = $c->req->upload('trial_upload_plot_gps_file');
1715 my $subdirectory = "trial_plot_gps_upload";
1716 my $upload_original_name = $upload->filename();
1717 my $upload_tempfile = $upload->tempname;
1718 my $time = DateTime->now();
1719 my $timestamp = $time->ymd()."_".$time->hms();
1721 ## Store uploaded temporary file in archive
1722 my $uploader = CXGN::UploadFile->new({
1723 tempfile => $upload_tempfile,
1724 subdirectory => $subdirectory,
1725 archive_path => $c->config->{archive_path},
1726 archive_filename => $upload_original_name,
1727 timestamp => $timestamp,
1728 user_id => $user_id,
1729 user_role => $user_role
1731 my $archived_filename_with_path = $uploader->archive();
1732 my $md5 = $uploader->get_md5($archived_filename_with_path);
1733 if (!$archived_filename_with_path) {
1734 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1735 $c->detach();
1737 unlink $upload_tempfile;
1738 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
1739 $parser->load_plugin('TrialPlotGPSCoordinatesXLS');
1740 my $parsed_data = $parser->parse();
1741 #print STDERR Dumper $parsed_data;
1743 if (!$parsed_data) {
1744 my $return_error = '';
1745 my $parse_errors;
1746 if (!$parser->has_parse_errors() ){
1747 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1748 $c->detach();
1749 } else {
1750 $parse_errors = $parser->get_parse_errors();
1751 #print STDERR Dumper $parse_errors;
1753 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1754 $return_error .= $error_string."<br>";
1757 $c->stash->{rest} = {error_string => $return_error, missing_plots => $parse_errors->{'missing_plots'}};
1758 $c->detach();
1761 my $stock_geo_json_cvterm = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot_geo_json', 'stock_property');
1763 my $upload_plot_gps_txn = sub {
1764 my %plot_stock_ids_hash;
1765 while (my ($key, $val) = each(%$parsed_data)){
1766 $plot_stock_ids_hash{$val->{plot_stock_id}} = $val;
1768 my @plot_stock_ids = keys %plot_stock_ids_hash;
1769 my $plots_rs = $schema->resultset("Stock::Stock")->search({stock_id => {-in=>\@plot_stock_ids}});
1770 while (my $plot=$plots_rs->next){
1771 my $coords = $plot_stock_ids_hash{$plot->stock_id};
1772 my $geo_json = {
1773 "type"=> "Feature",
1774 "geometry"=> {
1775 "type"=> "Polygon",
1776 "coordinates"=> [
1778 [$coords->{WGS84_bottom_left_x}, $coords->{WGS84_bottom_left_y}],
1779 [$coords->{WGS84_bottom_right_x}, $coords->{WGS84_bottom_right_y}],
1780 [$coords->{WGS84_top_right_x}, $coords->{WGS84_top_right_y}],
1781 [$coords->{WGS84_top_left_x}, $coords->{WGS84_top_left_y}],
1782 [$coords->{WGS84_bottom_left_x}, $coords->{WGS84_bottom_left_y}],
1786 "properties"=> {
1787 "format"=> "WGS84",
1790 my $geno_json_string = encode_json $geo_json;
1791 #print STDERR $geno_json_string."\n";
1792 my $previous_plot_gps_rs = $schema->resultset("Stock::Stockprop")->search({stock_id=>$plot->stock_id, type_id=>$stock_geo_json_cvterm->cvterm_id});
1793 $previous_plot_gps_rs->delete_all();
1794 $plot->create_stockprops({$stock_geo_json_cvterm->name() => $geno_json_string});
1796 my $layout = $c->stash->{trial_layout};
1797 $layout->generate_and_cache_layout();
1799 eval {
1800 $schema->txn_do($upload_plot_gps_txn);
1802 if ($@) {
1803 $c->stash->{rest} = { error => $@ };
1804 print STDERR "An error condition occurred, was not able to upload trial plot GPS coordinates. ($@).\n";
1805 $c->detach();
1808 my $dbh = $c->dbc->dbh();
1809 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1810 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1812 $c->stash->{rest} = { success => 1 };
1815 sub trial_change_plot_accessions_upload : Chained('trial') PathPart('change_plot_accessions_using_file') Args(1) {
1816 my $self = shift;
1817 my $c = shift;
1818 my $override = shift;
1819 my $trial_id = $c->stash->{trial_id};
1820 my $schema = $c->dbic_schema('Bio::Chado::Schema');
1822 if (!$c->user){
1823 $c->stash->{rest} = {error=>'You must be logged in to upload this seedlot info!'};
1824 return;
1828 my $upload = $c->req->upload('trial_design_change_accessions_file');
1829 my $subdirectory = "trial_change_plot_accessions_upload";
1830 my $upload_original_name = $upload->filename();
1831 my $upload_tempfile = $upload->tempname;
1832 my $time = DateTime->now();
1833 my $timestamp = $time->ymd()."_".$time->hms();
1835 ## Store uploaded temporary file in archive
1836 my $uploader = CXGN::UploadFile->new({
1837 tempfile => $upload_tempfile,
1838 subdirectory => $subdirectory,
1839 archive_path => $c->config->{archive_path},
1840 archive_filename => $upload_original_name,
1841 timestamp => $timestamp,
1842 user_id => $c->user->get_object->get_sp_person_id(),
1843 user_role => ($c->user->get_roles)[0]
1845 my $archived_filename_with_path = $uploader->archive();
1846 my $md5 = $uploader->get_md5($archived_filename_with_path);
1847 if (!$archived_filename_with_path) {
1848 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1849 $c->detach();
1851 unlink $upload_tempfile;
1852 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path, trial_id => $trial_id);
1853 $parser->load_plugin('TrialChangePlotAccessionsCSV');
1854 my $parsed_data = $parser->parse();
1855 #print STDERR Dumper $parsed_data;
1857 if (!$parsed_data) {
1858 my $return_error = '';
1859 my $parse_errors;
1860 if (!$parser->has_parse_errors() ){
1861 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
1862 $c->detach();
1863 } else {
1864 $parse_errors = $parser->get_parse_errors();
1865 #print STDERR Dumper $parse_errors;
1866 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
1867 $return_error .= $error_string."<br>";
1870 $c->stash->{rest} = {error => $return_error};
1871 return;
1874 my $plot_of_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot_of', 'stock_relationship')->cvterm_id();
1875 my $plot_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot', 'stock_type')->cvterm_id();
1877 my $replace_accession_fieldmap = CXGN::Trial::FieldMap->new({
1878 bcs_schema => $schema,
1879 trial_id => $trial_id,
1882 my $return_error = $replace_accession_fieldmap->update_fieldmap_precheck();
1883 if ($c->user()->check_roles("curator") and $return_error) {
1884 if ($override eq "check") {
1885 $c->stash->{rest} = { warning => "curator warning" };
1886 return;
1888 } elsif ($return_error){
1889 $c->stash->{rest} = { error => $return_error };
1890 return;
1893 my $upload_change_plot_accessions_txn = sub {
1894 my @stock_names;
1895 print STDERR Dumper $parsed_data;
1896 while (my ($key, $val) = each(%$parsed_data)){
1897 my $plot_name = $val->{plot_name};
1898 my $accession_name = $val->{accession_name};
1899 my $new_plot_name = $val->{new_plot_name};
1900 push @stock_names, $plot_name;
1901 push @stock_names, $accession_name;
1903 my %stock_id_map;
1904 my $stock_rs = $schema->resultset("Stock::Stock")->search({
1905 uniquename => {'-in' => \@stock_names}
1907 while (my $r = $stock_rs->next()){
1908 $stock_id_map{$r->uniquename} = $r->stock_id;
1910 print STDERR Dumper \%stock_id_map;
1911 while (my ($key, $val) = each(%$parsed_data)){
1912 my $plot_id = $stock_id_map{$val->{plot_name}};
1913 my $accession_id = $stock_id_map{$val->{accession_name}};
1914 my $plot_name = $val->{plot_name};
1915 my $new_plot_name = $val->{new_plot_name};
1917 my $replace_accession_error = $replace_accession_fieldmap->replace_plot_accession_fieldMap($plot_id, $accession_id, $plot_of_type_id);
1918 if ($replace_accession_error) {
1919 $c->stash->{rest} = { error => $replace_accession_error};
1920 return;
1923 if ($new_plot_name) {
1924 my $replace_plot_name_error = $replace_accession_fieldmap->replace_plot_name_fieldMap($plot_id, $new_plot_name);
1925 if ($replace_plot_name_error) {
1926 $c->stash->{rest} = { error => $replace_plot_name_error};
1927 return;
1932 eval {
1933 $schema->txn_do($upload_change_plot_accessions_txn);
1935 if ($@) {
1936 $c->stash->{rest} = { error => $@ };
1937 print STDERR "An error condition occurred, was not able to change plot accessions. ($@).\n";
1938 $c->detach();
1941 my $dbh = $c->dbc->dbh();
1942 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1943 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
1945 $c->stash->{rest} = { success => 1 };
1948 sub trial_additional_file_upload : Chained('trial') PathPart('upload_additional_file') Args(0) {
1949 my $self = shift;
1950 my $c = shift;
1951 my $user_id;
1952 my $user_name;
1953 my $user_role;
1954 my $session_id = $c->req->param("sgn_session_id");
1956 if ($session_id){
1957 my $dbh = $c->dbc->dbh;
1958 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
1959 if (!$user_info[0]){
1960 $c->stash->{rest} = {error=>'You must be logged in to upload additional trials to a file!'};
1961 $c->detach();
1963 $user_id = $user_info[0];
1964 $user_role = $user_info[1];
1965 my $p = CXGN::People::Person->new($dbh, $user_id);
1966 $user_name = $p->get_username;
1967 } else{
1968 if (!$c->user){
1969 $c->stash->{rest} = {error=>'You must be logged in to upload additional files to a trial!'};
1970 $c->detach();
1972 $user_id = $c->user()->get_object()->get_sp_person_id();
1973 $user_name = $c->user()->get_object()->get_username();
1974 $user_role = $c->user->get_object->get_user_type();
1977 my $upload = $c->req->upload('trial_upload_additional_file');
1978 my $subdirectory = "trial_additional_file_upload";
1979 my $upload_original_name = $upload->filename();
1980 my $upload_tempfile = $upload->tempname;
1981 my $time = DateTime->now();
1982 my $timestamp = $time->ymd()."_".$time->hms();
1984 ## Store uploaded temporary file in archive
1985 my $uploader = CXGN::UploadFile->new({
1986 tempfile => $upload_tempfile,
1987 subdirectory => $subdirectory,
1988 archive_path => $c->config->{archive_path},
1989 archive_filename => $upload_original_name,
1990 timestamp => $timestamp,
1991 user_id => $user_id,
1992 user_role => $user_role
1994 my $archived_filename_with_path = $uploader->archive();
1995 my $md5 = $uploader->get_md5($archived_filename_with_path);
1996 if (!$archived_filename_with_path) {
1997 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
1998 $c->detach();
2000 unlink $upload_tempfile;
2001 my $md5checksum = $md5->hexdigest();
2003 my $result = $c->stash->{trial}->add_additional_uploaded_file($user_id, $archived_filename_with_path, $md5checksum);
2004 if ($result->{error}){
2005 $c->stash->{rest} = {error=>$result->{error}};
2006 $c->detach();
2008 $c->stash->{rest} = { success => 1, file_id => $result->{file_id} };
2011 sub get_trial_additional_file_uploaded : Chained('trial') PathPart('get_uploaded_additional_file') Args(0) {
2012 my $self = shift;
2013 my $c = shift;
2015 if (!$c->user){
2016 $c->stash->{rest} = {error=>'You must be logged in to see uploaded additional files!'};
2017 $c->detach();
2020 my $files = $c->stash->{trial}->get_additional_uploaded_files();
2021 $c->stash->{rest} = {success=>1, files=>$files};
2024 sub obsolete_trial_additional_file_uploaded :Chained('trial') PathPart('obsolete_uploaded_additional_file') Args(1) {
2025 my $self = shift;
2026 my $c = shift;
2027 my $file_id = shift;
2029 if (!$c->user) {
2030 $c->stash->{rest} = { error => "You must be logged in to obsolete additional files!" };
2031 $c->detach();
2034 my $user_id = $c->user->get_object()->get_sp_person_id();
2036 my @roles = $c->user->roles();
2037 my $result = $c->stash->{trial}->obsolete_additional_uploaded_file($file_id, $user_id, $roles[0]);
2039 if (exists($result->{errors})) {
2040 $c->stash->{rest} = { error => $result->{errors} };
2042 else {
2043 $c->stash->{rest} = { success => 1 };
2049 sub trial_controls : Chained('trial') PathPart('controls') Args(0) {
2050 my $self = shift;
2051 my $c = shift;
2052 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2054 my $trial = CXGN::Trial->new( { bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
2056 my @data = $trial->get_controls();
2058 $c->stash->{rest} = { accessions => \@data };
2061 sub controls_by_plot : Chained('trial') PathPart('controls_by_plot') Args(0) {
2062 my $self = shift;
2063 my $c = shift;
2064 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2065 my @plot_ids = $c->req->param('plot_ids[]');
2067 my $trial = CXGN::Trial->new({ bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
2069 my @data = $trial->get_controls_by_plot(\@plot_ids);
2071 $c->stash->{rest} = { accessions => \@data };
2074 sub trial_plots : Chained('trial') PathPart('plots') Args(0) {
2075 my $self = shift;
2076 my $c = shift;
2077 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2079 my $trial = $c->stash->{trial};
2081 my @data = $trial->get_plots();
2082 # print STDERR "PLOTS =".Dumper(\@data)."\n";
2084 $c->stash->{rest} = { plots => \@data };
2087 sub trial_has_data_levels : Chained('trial') PathPart('has_data_levels') Args(0) {
2088 my $self = shift;
2089 my $c = shift;
2090 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2092 my $trial = $c->stash->{trial};
2093 $c->stash->{rest} = {
2094 has_plants => $trial->has_plant_entries(),
2095 has_subplots => $trial->has_subplot_entries(),
2096 has_tissue_samples => $trial->has_tissue_sample_entries(),
2097 trial_name => $trial->get_name
2101 sub trial_has_subplots : Chained('trial') PathPart('has_subplots') Args(0) {
2102 my $self = shift;
2103 my $c = shift;
2104 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2106 my $trial = $c->stash->{trial};
2107 $c->stash->{rest} = { has_subplots => $trial->has_subplot_entries(), trial_name => $trial->get_name };
2110 sub trial_subplots : Chained('trial') PathPart('subplots') Args(0) {
2111 my $self = shift;
2112 my $c = shift;
2113 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2115 my $trial = $c->stash->{trial};
2117 my @data = $trial->get_subplots();
2119 $c->stash->{rest} = { subplots => \@data };
2122 sub trial_has_plants : Chained('trial') PathPart('has_plants') Args(0) {
2123 my $self = shift;
2124 my $c = shift;
2125 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2127 my $trial = $c->stash->{trial};
2128 $c->stash->{rest} = { has_plants => $trial->has_plant_entries(), trial_name => $trial->get_name };
2131 sub trial_plants : Chained('trial') PathPart('plants') Args(0) {
2132 my $self = shift;
2133 my $c = shift;
2134 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2136 my $trial = $c->stash->{trial};
2138 my @data = $trial->get_plants();
2140 $c->stash->{rest} = { plants => \@data };
2143 sub trial_has_tissue_samples : Chained('trial') PathPart('has_tissue_samples') Args(0) {
2144 my $self = shift;
2145 my $c = shift;
2146 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2148 my $trial = $c->stash->{trial};
2149 $c->stash->{rest} = { has_tissue_samples => $trial->has_tissue_sample_entries(), trial_name => $trial->get_name };
2152 sub trial_tissue_samples : Chained('trial') PathPart('tissue_samples') Args(0) {
2153 my $self = shift;
2154 my $c = shift;
2155 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2157 my $trial = $c->stash->{trial};
2159 my $data = $trial->get_tissue_samples();
2161 $c->stash->{rest} = { trial_tissue_samples => $data };
2164 sub trial_phenotype_metadata : Chained('trial') PathPart('phenotype_metadata') Args(0) {
2165 my $self = shift;
2166 my $c = shift;
2168 my $trial = $c->stash->{trial};
2169 my $data = $trial->get_phenotype_metadata();
2171 $c->stash->{rest} = { data => $data };
2174 sub trial_treatments : Chained('trial') PathPart('treatments') Args(0) {
2175 my $self = shift;
2176 my $c = shift;
2177 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2179 my $trial = $c->stash->{trial};
2181 my $data = $trial->get_treatments();
2183 $c->stash->{rest} = { treatments => $data };
2186 sub trial_add_treatment : Chained('trial') PathPart('add_treatment') Args(0) {
2187 my $self = shift;
2188 my $c = shift;
2190 if (!$c->user()){
2191 $c->stash->{rest} = {error => "You must be logged in to add a treatment"};
2192 $c->detach();
2195 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2196 my $trial_id = $c->stash->{trial_id};
2197 my $trial = $c->stash->{trial};
2198 my $design = decode_json $c->req->param('design');
2199 my $new_treatment_has_plant_entries = $c->req->param('has_plant_entries');
2200 my $new_treatment_has_subplot_entries = $c->req->param('has_subplot_entries');
2201 my $new_treatment_has_tissue_entries = $c->req->param('has_tissue_sample_entries');
2202 my $new_treatment_year = $c->req->param('treatment_year');
2203 my $new_treatment_date = $c->req->param('treatment_date');
2204 my $new_treatment_type = $c->req->param('treatment_type');
2206 my $trial_design_store = CXGN::Trial::TrialDesignStore->new({
2207 bcs_schema => $schema,
2208 trial_id => $trial_id,
2209 trial_name => $trial->get_name(),
2210 nd_geolocation_id => $trial->get_location()->[0],
2211 design_type => $trial->get_design_type(),
2212 design => $design,
2213 new_treatment_has_plant_entries => $new_treatment_has_plant_entries,
2214 new_treatment_has_subplot_entries => $new_treatment_has_subplot_entries,
2215 new_treatment_has_tissue_sample_entries => $new_treatment_has_tissue_entries,
2216 new_treatment_date => $new_treatment_date,
2217 new_treatment_year => $new_treatment_year,
2218 new_treatment_type => $new_treatment_type,
2219 operator => $c->user()->get_object()->get_username()
2221 my $error = $trial_design_store->store();
2222 if ($error){
2223 $c->stash->{rest} = {error => "Treatment not added: ".$error};
2224 } else {
2225 $c->stash->{rest} = {success => 1};
2229 sub trial_layout : Chained('trial') PathPart('layout') Args(0) {
2230 my $self = shift;
2231 my $c = shift;
2232 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2234 my $layout = $c->stash->{trial_layout};
2236 my $design = $layout->get_design();
2237 $c->stash->{rest} = {design => $design};
2240 sub trial_layout_table : Chained('trial') PathPart('layout_table') Args(0) {
2241 my $self = shift;
2242 my $c = shift;
2243 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2244 my $selected_cols = $c->req->param('selected_columns') ? decode_json $c->req->param('selected_columns') : {"plot_name"=>1,"plot_number"=>1,"block_number"=>1,"accession_name"=>1,"is_a_control"=>1,"rep_number"=>1,"row_number"=>1,"col_number"=>1,"plot_geo_json"=>1};
2246 my $trial_layout_download = CXGN::Trial::TrialLayoutDownload->new({
2247 schema => $schema,
2248 trial_id => $c->stash->{trial_id},
2249 data_level => 'plots',
2250 #treatment_project_ids => [1,2],
2251 selected_columns => $selected_cols,
2252 include_measured => "false"
2254 my $output = $trial_layout_download->get_layout_output();
2256 $c->stash->{rest} = $output;
2259 sub trial_design : Chained('trial') PathPart('design') Args(0) {
2260 my $self = shift;
2261 my $c = shift;
2262 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2264 my $layout = $c->stash->{trial_layout};
2266 my $design = $layout->get_design();
2267 my $design_type = $layout->get_design_type();
2269 my $plot_length = '';
2270 my $plot_width = '';
2271 my $subplots_per_plot = '';
2272 my $plants_per_plot = '';
2273 my $number_of_blocks = '';
2274 if ($design_type ne 'genotyping_plate') {
2275 my $plot_dimensions = $layout->get_plot_dimensions();
2276 $plot_length = $plot_dimensions->[0] ? $plot_dimensions->[0] : '';
2277 $plot_width = $plot_dimensions->[1] ? $plot_dimensions->[1] : '';
2278 $plants_per_plot = $plot_dimensions->[2] ? $plot_dimensions->[2] : '';
2279 $subplots_per_plot = $plot_dimensions->[3] ? $plot_dimensions->[3] : '';
2281 my $block_numbers = $layout->get_block_numbers();
2282 if ($block_numbers) {
2283 $number_of_blocks = scalar(@{$block_numbers});
2287 my $replicate_numbers = $layout->get_replicate_numbers();
2288 my $number_of_replicates = '';
2289 if ($replicate_numbers) {
2290 $number_of_replicates = scalar(@{$replicate_numbers});
2293 my $plot_names = $layout->get_plot_names();
2294 my $number_of_plots = '';
2295 if ($plot_names){
2296 $number_of_plots = scalar(@{$plot_names});
2299 $c->stash->{rest} = {
2300 design_type => $design_type,
2301 num_blocks => $number_of_blocks,
2302 num_reps => $number_of_replicates,
2303 plot_length => $plot_length,
2304 plot_width => $plot_width,
2305 subplots_per_plot => $subplots_per_plot,
2306 plants_per_plot => $plants_per_plot,
2307 total_number_plots => $number_of_plots,
2308 design => $design
2312 sub get_spatial_layout : Chained('trial') PathPart('coords') Args(0) {
2314 my $self = shift;
2315 my $c = shift;
2316 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2318 my $cxgn_project_type = $c->stash->{trial}->get_cxgn_project_type();
2320 my $fieldmap = CXGN::Trial::FieldMap->new({
2321 bcs_schema => $schema,
2322 trial_id => $c->stash->{trial_id},
2323 experiment_type => $cxgn_project_type->{experiment_type}
2325 my $return = $fieldmap->display_fieldmap();
2327 $c->stash->{rest} = $return;
2330 sub retrieve_trial_info : Path('/ajax/breeders/trial_phenotyping_info') : ActionClass('REST') { }
2331 sub retrieve_trial_info_POST : Args(0) {
2332 #sub retrieve_trial_info : chained('trial') Pathpart("trial_phenotyping_info") Args(0) {
2333 my $self =shift;
2334 my $c = shift;
2335 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
2336 my $trial_id = $c->req->param('trial_id');
2337 my $layout = CXGN::Trial::TrialLayout->new({schema => $schema, trial_id => $trial_id, experiment_type=>'field_layout'});
2338 my $design = $layout-> get_design();
2339 #print STDERR Dumper($design);
2341 my @layout_info;
2342 foreach my $plot_number (keys %{$design}) {
2343 push @layout_info, {
2344 plot_id => $design->{$plot_number}->{plot_id},
2345 plot_number => $plot_number,
2346 row_number => $design->{$plot_number}->{row_number},
2347 col_number => $design->{$plot_number}->{col_number},
2348 block_number=> $design->{$plot_number}-> {block_number},
2349 rep_number => $design->{$plot_number}-> {rep_number},
2350 plot_name => $design->{$plot_number}-> {plot_name},
2351 accession_name => $design->{$plot_number}-> {accession_name},
2352 plant_names => $design->{$plot_number}-> {plant_names},
2354 @layout_info = sort { $a->{plot_number} <=> $b->{plot_number} } @layout_info;
2357 #print STDERR Dumper(@layout_info);
2358 $c->stash->{rest} = {trial_info => \@layout_info};
2359 #$c->stash->{layout_info} = \@layout_info;
2363 sub trial_completion_layout_section : Chained('trial') PathPart('trial_completion_layout_section') Args(0) {
2364 my $self = shift;
2365 my $c = shift;
2366 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2367 my $experiment_type = $c->req->param('experiment_type') || 'field_layout';
2369 my $trial_layout = CXGN::Trial::TrialLayout->new({schema => $schema, trial_id => $c->stash->{trial_id}, experiment_type => $experiment_type, verify_layout=>1, verify_physical_map=>1});
2370 my $trial_errors = $trial_layout->generate_and_cache_layout();
2371 my $has_layout_check = $trial_errors->{errors}->{layout_errors} || $trial_errors->{error} ? 0 : 1;
2372 my $has_physical_map_check = $trial_errors->{errors}->{physical_map_errors} || $trial_errors->{error} ? 0 : 1;
2373 my $has_seedlots = $trial_errors->{errors}->{seedlot_errors} || $trial_errors->{error} ? 0 : 1;
2374 my $error_string = $trial_errors->{error} ? $trial_errors->{error} : '';
2375 my $layout_error_string = $trial_errors->{errors}->{layout_errors} ? join ', ', @{$trial_errors->{errors}->{layout_errors}} : '';
2376 my $map_error_string = $trial_errors->{errors}->{physical_map_errors} ? join ', ', @{$trial_errors->{errors}->{physical_map_errors}} : '';
2377 my $seedlot_error_string = $trial_errors->{errors}->{seedlot_errors} ? join ', ', @{$trial_errors->{errors}->{seedlot_errors}} : '';
2379 $c->stash->{rest} = {
2380 has_layout => $has_layout_check,
2381 layout_errors => $error_string." ".$layout_error_string,
2382 has_physical_map => $has_physical_map_check,
2383 physical_map_errors => $error_string." ".$map_error_string,
2384 has_seedlots => $has_seedlots,
2385 seedlot_errors => $error_string." ".$seedlot_error_string
2389 sub trial_completion_phenotype_section : Chained('trial') PathPart('trial_completion_phenotype_section') Args(0) {
2390 my $self = shift;
2391 my $c = shift;
2392 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2394 my $plot_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot', 'stock_type')->cvterm_id();
2395 my $plant_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plant', 'stock_type')->cvterm_id();
2396 my $phenotyping_experiment_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'phenotyping_experiment', 'experiment_type')->cvterm_id();
2397 my $has_phenotype_check = $schema->resultset('Phenotype::Phenotype')->search({'stock.type_id'=> [$plot_type_id, $plant_type_id], 'nd_experiment.type_id'=>$phenotyping_experiment_type_id, 'me.value' => { '!=' => ''}, 'project.project_id'=>$c->stash->{trial_id}}, {join=>{'nd_experiment_phenotypes'=>{'nd_experiment'=>[{'nd_experiment_stocks'=>'stock' }, {'nd_experiment_projects'=>'project'}] } }, rows=>1 });
2398 my $has_phenotypes = $has_phenotype_check->first ? 1 : 0;
2400 $c->stash->{rest} = {has_phenotypes => $has_phenotypes};
2403 sub delete_field_coord : Path('/ajax/phenotype/delete_field_coords') Args(0) {
2404 my $self = shift;
2405 my $c = shift;
2406 my $trial_id = $c->req->param('trial_id');
2408 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2410 if ($self->privileges_denied($c)) {
2411 $c->stash->{rest} = { error => "You have insufficient access privileges to update this map." };
2412 return;
2415 my $fieldmap = CXGN::Trial::FieldMap->new({
2416 bcs_schema => $schema,
2417 trial_id => $trial_id,
2419 my $delete_return_error = $fieldmap->delete_fieldmap();
2420 if ($delete_return_error) {
2421 $c->stash->{rest} = { error => $delete_return_error };
2422 return;
2425 my $dbh = $c->dbc->dbh();
2426 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
2427 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'phenotypes', 'concurrent', $c->config->{basepath});
2428 my $trial_layout = CXGN::Trial::TrialLayout->new({ schema => $schema, trial_id => $trial_id, experiment_type => 'field_layout' });
2429 $trial_layout->generate_and_cache_layout();
2431 $c->stash->{rest} = {success => 1};
2434 sub replace_trial_stock : Chained('trial') PathPart('replace_stock') Args(0) {
2435 my $self = shift;
2436 my $c = shift;
2437 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2438 my $old_stock_id = $c->req->param('old_stock_id');
2439 my $new_stock = $c->req->param('new_stock');
2440 my $trial_stock_type = $c->req->param('trial_stock_type');
2441 my $trial_id = $c->stash->{trial_id};
2443 if ($self->privileges_denied($c)) {
2444 $c->stash->{rest} = { error => "You have insufficient access privileges to edit this map." };
2445 return;
2448 if (!$new_stock){
2449 $c->stash->{rest} = { error => "Provide new stock name." };
2450 return;
2453 my $replace_stock_fieldmap = CXGN::Trial::FieldMap->new({
2454 bcs_schema => $schema,
2455 trial_id => $trial_id,
2456 trial_stock_type => $trial_stock_type,
2460 my $return_error = $replace_stock_fieldmap->update_fieldmap_precheck();
2461 if ($return_error) {
2462 $c->stash->{rest} = { error => $return_error };
2463 return;
2466 my $replace_return_error = $replace_stock_fieldmap->replace_trial_stock_fieldMap($new_stock, $old_stock_id);
2467 if ($replace_return_error) {
2468 $c->stash->{rest} = { error => $replace_return_error };
2469 return;
2472 $c->stash->{rest} = { success => 1};
2475 sub refresh_cache : Chained('trial') PathPart('refresh_cache') Args(0) {
2476 my $self = shift;
2477 my $c = shift;
2478 my $trial_id = $c->stash->{trial_id};
2479 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2481 my $refresh_fieldmap_cache = CXGN::Trial::FieldMap->new({
2482 trial_id => $trial_id,
2483 bcs_schema => $schema,
2486 $refresh_fieldmap_cache->_regenerate_trial_layout_cache();
2487 $c->stash->{rest} = { success => 1};
2490 sub replace_plot_accession : Chained('trial') PathPart('replace_plot_accessions') Args(0) {
2491 my $self = shift;
2492 my $c = shift;
2493 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2494 my $old_accession = $c->req->param('old_accession');
2495 my $new_accession = $c->req->param('new_accession');
2496 my $plot_id = $c->req->param('old_plot_id');
2497 my $old_plot_name = $c->req->param('old_plot_name');
2498 my $new_plot_name = $c->req->param('new_plot_name');
2499 my $override = $c->req->param('override');
2500 my $trial_id = $c->stash->{trial_id};
2502 if (!$c->user){
2503 $c->stash->{rest} = {error=>'You must be logged in to change a plot accession!'};
2504 return;
2507 if ($self->privileges_denied($c)) {
2508 $c->stash->{rest} = { error => "You have insufficient access privileges to edit this map." };
2509 return;
2512 if (!$new_accession) {
2513 $c->stash->{rest} = { error => "Provide new accession name." };
2514 return;
2517 my $replace_plot_accession_fieldmap = CXGN::Trial::FieldMap->new({
2518 trial_id => $trial_id,
2519 bcs_schema => $schema,
2522 my $return_error = $replace_plot_accession_fieldmap->update_fieldmap_precheck();
2524 if ($c->user()->check_roles("curator") and $return_error) {
2525 if ($override eq "check") {
2526 $c->stash->{rest} = { warning => "curator warning" };
2527 return;
2529 } elsif ($return_error) {
2530 $c->stash->{rest} = { error => $return_error};
2531 return;
2535 my $plot_of_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'plot_of', 'stock_relationship')->cvterm_id();
2536 my $accession_rs = $schema->resultset("Stock::Stock")->search({
2537 uniquename => $new_accession
2539 $accession_rs = $accession_rs->next();
2540 my $accession_id = $accession_rs->stock_id;
2542 print "Calling Replace Function...............\n";
2543 my $replace_return_error = $replace_plot_accession_fieldmap->replace_plot_accession_fieldMap($plot_id, $accession_id, $plot_of_type_id);
2544 if ($replace_return_error) {
2545 $c->stash->{rest} = { error => $replace_return_error };
2546 return;
2549 if ($new_plot_name) {
2550 my $replace_plot_name_return_error = $replace_plot_accession_fieldmap->replace_plot_name_fieldMap($plot_id, $new_plot_name);
2551 if ($replace_plot_name_return_error) {
2552 $c->stash->{rest} = { error => $replace_plot_name_return_error };
2553 return;
2556 my $dbh = $c->dbc->dbh();
2557 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
2558 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'phenotypes', 'concurrent', $c->config->{basepath});
2560 print "OldAccession: $old_accession, NewAcc: $new_accession, OldPlotName: $old_plot_name, NewPlotName: $new_plot_name OldPlotId: $plot_id\n";
2561 $c->stash->{rest} = { success => 1};
2564 sub accession_exists : Chained('trial') PathPart('accession_exists') Args(0) {
2565 my $self = shift;
2566 my $c = shift;
2567 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2568 my $accession_name = $c->req->param('accession_name');
2569 my $rs = $schema->resultset("Stock::Stock")->search({uniquename=> $accession_name });
2570 if (!$rs->first()) {
2571 $c->stash->{rest} = { error => "Error: $accession_name is not a valid accession in the database." };
2572 return;
2574 my $accession_id = $rs->first()->stock_id();
2575 $c->stash->{rest} = { success => $accession_id};
2578 sub check_curator_privileges : Chained('trial') PathPart('check_curator_privileges') Args(0) {
2579 my $self = shift;
2580 my $c = shift;
2582 if ($c->user()->check_roles("curator")) {
2583 $c->stash->{rest} = { success => 1};
2584 } else {
2585 $c->stash->{rest} = { error => "You have insufficient access privileges to edit this map." };
2590 sub replace_well_accession : Chained('trial') PathPart('replace_well_accessions') Args(0) {
2591 my $self = shift;
2592 my $c = shift;
2593 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2594 my $old_accession = $c->req->param('old_accession');
2595 my $new_accession = $c->req->param('new_accession');
2596 my $old_plot_id = $c->req->param('old_plot_id');
2597 my $old_plot_name = $c->req->param('old_plot_name');
2598 my $trial_id = $c->stash->{trial_id};
2600 if ($self->privileges_denied($c)) {
2601 $c->stash->{rest} = { error => "You have insufficient access privileges to edit this map." };
2602 return;
2605 if (!$new_accession){
2606 $c->stash->{rest} = { error => "Provide new accession name." };
2607 return;
2609 my $cxgn_project_type = $c->stash->{trial}->get_cxgn_project_type();
2611 my $replace_plot_accession_fieldmap = CXGN::Trial::FieldMap->new({
2612 bcs_schema => $schema,
2613 trial_id => $trial_id,
2614 new_accession => $new_accession,
2615 old_accession => $old_accession,
2616 old_plot_id => $old_plot_id,
2617 old_plot_name => $old_plot_name,
2618 experiment_type => $cxgn_project_type->{experiment_type}
2621 my $return_error = $replace_plot_accession_fieldmap->update_fieldmap_precheck();
2622 if ($return_error) {
2623 $c->stash->{rest} = { error => $return_error };
2624 return;
2627 print "Calling Replace Function...............\n";
2628 my $replace_return_error = $replace_plot_accession_fieldmap->replace_plot_accession_fieldMap();
2629 if ($replace_return_error) {
2630 $c->stash->{rest} = { error => $replace_return_error };
2631 return;
2634 print "OldAccession: $old_accession, NewAcc: $new_accession, OldWellId: $old_plot_id\n";
2635 $c->stash->{rest} = { success => 1};
2638 sub substitute_stock : Chained('trial') PathPart('substitute_stock') Args(0) {
2639 my $self = shift;
2640 my $c = shift;
2641 my $schema = $c->dbic_schema('Bio::Chado::Schema');
2642 my $trial_id = $c->stash->{trial_id};
2643 my $plot_1_info = $c->req->param('plot_1_info');
2644 my $plot_2_info = $c->req->param('plot_2_info');
2646 my ($plot_1_id, $accession_1) = split /,/, $plot_1_info;
2647 my ($plot_2_id, $accession_2) = split /,/, $plot_2_info;
2649 if ($self->privileges_denied($c)) {
2650 $c->stash->{rest} = { error => "You have insufficient access privileges to update this map." };
2651 return;
2654 if ($plot_1_id == $plot_2_id){
2655 $c->stash->{rest} = { error => "Choose a different plot/stock in 'select plot 2' to perform this operation." };
2656 return;
2659 my @controls;
2660 my @ids;
2662 my $fieldmap = CXGN::Trial::FieldMap->new({
2663 bcs_schema => $schema,
2664 trial_id => $trial_id,
2665 first_plot_selected => $plot_1_id,
2666 second_plot_selected => $plot_2_id,
2667 first_accession_selected => $accession_1,
2668 second_accession_selected => $accession_2,
2671 my $return_error = $fieldmap->update_fieldmap_precheck();
2672 if ($return_error) {
2673 $c->stash->{rest} = { error => $return_error };
2674 return;
2677 my $return_check_error = $fieldmap->substitute_accession_precheck();
2678 if ($return_check_error) {
2679 $c->stash->{rest} = { error => $return_check_error };
2680 return;
2683 my $update_return_error = $fieldmap->substitute_accession_fieldmap();
2684 if ($update_return_error) {
2685 $c->stash->{rest} = { error => $update_return_error };
2686 return;
2689 $c->stash->{rest} = { success => 1};
2692 sub create_plant_plot_entries : Chained('trial') PathPart('create_plant_entries') Args(0) {
2693 my $self = shift;
2694 my $c = shift;
2695 my $plant_owner = $c->user->get_object->get_sp_person_id;
2696 my $plant_owner_username = $c->user->get_object->get_username;
2697 my $plants_per_plot = $c->req->param("plants_per_plot") || 8;
2698 my $inherits_plot_treatments = $c->req->param("inherits_plot_treatments");
2699 my $plants_with_treatments;
2700 if($inherits_plot_treatments eq '1'){
2701 $plants_with_treatments = 1;
2704 if (my $error = $self->privileges_denied($c)) {
2705 $c->stash->{rest} = { error => $error };
2706 return;
2709 if (!$plants_per_plot || $plants_per_plot > 500) {
2710 $c->stash->{rest} = { error => "Plants per plot number is required and must be smaller than 500." };
2711 return;
2714 my $user_id = $c->user->get_object->get_sp_person_id();
2715 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
2717 if ($t->create_plant_entities($plants_per_plot, $plants_with_treatments, $user_id)) {
2718 my $dbh = $c->dbc->dbh();
2719 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
2720 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
2723 $c->stash->{rest} = {success => 1};
2724 return;
2725 } else {
2726 $c->stash->{rest} = { error => "Error creating plant entries in controller." };
2727 return;
2732 sub create_plant_subplot_entries : Chained('trial') PathPart('create_plant_subplot_entries') Args(0) {
2733 my $self = shift;
2734 my $c = shift;
2735 my $plant_owner = $c->user->get_object->get_sp_person_id;
2736 my $plant_owner_username = $c->user->get_object->get_username;
2737 my $plants_per_subplot = $c->req->param("plants_per_subplot") || 8;
2738 my $inherits_plot_treatments = $c->req->param("inherits_plot_treatments");
2739 my $plants_with_treatments;
2740 if($inherits_plot_treatments eq '1'){
2741 $plants_with_treatments = 1;
2744 if (my $error = $self->privileges_denied($c)) {
2745 $c->stash->{rest} = { error => $error };
2746 return;
2749 if (!$plants_per_subplot || $plants_per_subplot > 500) {
2750 $c->stash->{rest} = { error => "Plants per subplot number is required and must be smaller than 500." };
2751 return;
2754 my $user_id = $c->user->get_object->get_sp_person_id();
2755 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
2757 if ($t->create_plant_subplot_entities($plants_per_subplot, $plants_with_treatments, $user_id)) {
2759 my $dbh = $c->dbc->dbh();
2760 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
2761 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
2763 $c->stash->{rest} = {success => 1};
2764 return;
2765 } else {
2766 $c->stash->{rest} = { error => "Error creating plant entries for subplots in controller." };
2767 return;
2772 sub create_subplot_entries : Chained('trial') PathPart('create_subplot_entries') Args(0) {
2773 my $self = shift;
2774 my $c = shift;
2775 my $subplot_owner = $c->user->get_object->get_sp_person_id;
2776 my $subplot_owner_username = $c->user->get_object->get_username;
2777 my $subplots_per_plot = $c->req->param("subplots_per_plot") || 4;
2778 my $inherits_plot_treatments = $c->req->param("inherits_plot_treatments");
2779 my $subplots_with_treatments;
2780 if($inherits_plot_treatments eq '1'){
2781 $subplots_with_treatments = 1;
2784 if (my $error = $self->privileges_denied($c)) {
2785 $c->stash->{rest} = { error => $error };
2786 return;
2789 if (!$subplots_per_plot || $subplots_per_plot > 500) {
2790 $c->stash->{rest} = { error => "Subplots per plot number is required and must be smaller than 500." };
2791 return;
2794 my $user_id = $c->user->get_object->get_sp_person_id();
2795 my $t = CXGN::Trial->new( { bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
2797 if ($t->create_subplot_entities($subplots_per_plot, $subplots_with_treatments, $user_id)) {
2799 my $dbh = $c->dbc->dbh();
2800 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
2801 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
2803 $c->stash->{rest} = {success => 1};
2804 return;
2805 } else {
2806 $c->stash->{rest} = { error => "Error creating subplot entries in controller." };
2807 return;
2812 sub create_tissue_samples : Chained('trial') PathPart('create_tissue_samples') Args(0) {
2813 my $self = shift;
2814 my $c = shift;
2815 my $tissue_sample_owner = $c->user->get_object->get_sp_person_id;
2816 my $tissue_owner_username = $c->user->get_object->get_username;
2817 my $tissues_per_plant = $c->req->param("tissue_samples_per_plant") || 3;
2818 my $tissue_names = decode_json $c->req->param("tissue_samples_names");
2819 my $inherits_plot_treatments = $c->req->param("inherits_plot_treatments");
2820 my $tissues_with_treatments;
2821 if($inherits_plot_treatments eq '1'){
2822 $tissues_with_treatments = 1;
2825 if (my $error = $self->privileges_denied($c)) {
2826 $c->stash->{rest} = { error => $error };
2827 $c->detach;
2830 if (!$c->stash->{trial}->has_plant_entries){
2831 $c->stash->{rest} = { error => "Trial must have plant entries before you can add tissue samples entries. Plant entries are added from the trial detail page." };
2832 $c->detach;
2835 if (!$tissue_names || scalar(@$tissue_names) < 1){
2836 $c->stash->{rest} = { error => "You must provide tissue name(s) for your samples" };
2837 $c->detach;
2840 if (!$tissues_per_plant || $tissues_per_plant > 50) {
2841 $c->stash->{rest} = { error => "Tissues per plant is required and must be smaller than 50." };
2842 $c->detach;
2845 my $user_id = $c->user->get_object->get_sp_person_id();
2846 my $t = CXGN::Trial->new({ bcs_schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $c->stash->{trial_id} });
2848 if ($t->create_tissue_samples($tissue_names, $inherits_plot_treatments, $user_id)) {
2849 my $dbh = $c->dbc->dbh();
2850 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
2851 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
2853 $c->stash->{rest} = {success => 1};
2854 $c->detach;;
2855 } else {
2856 $c->stash->{rest} = { error => "Error creating tissues samples in controller." };
2857 $c->detach;;
2862 sub edit_management_factor_details : Chained('trial') PathPart('edit_management_factor_details') Args(0) {
2863 my $self = shift;
2864 my $c = shift;
2865 my $schema = $c->dbic_schema("Bio::Chado::Schema");
2866 my $treatment_date = $c->req->param("treatment_date");
2867 my $treatment_name = $c->req->param("treatment_name");
2868 my $treatment_description = $c->req->param("treatment_description");
2869 my $treatment_type = $c->req->param("treatment_type");
2870 my $treatment_year = $c->req->param("treatment_year");
2872 if (my $error = $self->privileges_denied($c)) {
2873 $c->stash->{rest} = { error => $error };
2874 return;
2877 if (!$treatment_name) {
2878 $c->stash->{rest} = { error => 'No treatment name given!' };
2879 return;
2881 if (!$treatment_description) {
2882 $c->stash->{rest} = { error => 'No treatment description given!' };
2883 return;
2885 if (!$treatment_date) {
2886 $c->stash->{rest} = { error => 'No treatment date given!' };
2887 return;
2889 if (!$treatment_type) {
2890 $c->stash->{rest} = { error => 'No treatment type given!' };
2891 return;
2893 if (!$treatment_year) {
2894 $c->stash->{rest} = { error => 'No treatment year given!' };
2895 return;
2898 my $t = CXGN::Trial->new( { bcs_schema => $schema, trial_id => $c->stash->{trial_id} });
2899 my $trial_name = $t->get_name();
2901 if ($trial_name ne $treatment_name) {
2902 my $trial_rs = $schema->resultset('Project::Project')->search({name => $treatment_name});
2903 if ($trial_rs->count() > 0) {
2904 $c->stash->{rest} = { error => 'Please use a different management factor name! That name is already in use.' };
2905 return;
2909 $t->set_name($treatment_name);
2910 $t->set_management_factor_date($treatment_date);
2911 $t->set_management_factor_type($treatment_type);
2912 $t->set_description($treatment_description);
2913 $t->set_year($treatment_year);
2915 $c->stash->{rest} = { success => 1 };
2918 sub privileges_denied {
2919 my $self = shift;
2920 my $c = shift;
2922 my $trial_id = $c->stash->{trial_id};
2924 if (! $c->user) { return "Login required for modifying trial."; }
2925 my $user_id = $c->user->get_object->get_sp_person_id();
2927 if ($c->user->check_roles('curator')) {
2928 return 0;
2931 my $breeding_programs = $c->stash->{trial}->get_breeding_programs();
2933 if ( ($c->user->check_roles('submitter')) && ( $c->user->check_roles($breeding_programs->[0]->[1]))) {
2934 return 0;
2936 return "You have insufficient privileges to modify or delete this trial.";
2939 # loading field coordinates
2941 sub upload_trial_coordinates : Path('/ajax/breeders/trial/coordsupload') Args(0) {
2942 my $self = shift;
2943 my $c = shift;
2944 my $user_id;
2945 my $user_name;
2946 my $user_role;
2947 my $session_id = $c->req->param("sgn_session_id");
2949 if ($session_id){
2950 my $dbh = $c->dbc->dbh;
2951 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
2952 if (!$user_info[0]){
2953 $c->stash->{rest} = {error=>'You must be logged in to upload plot coordinates (row and column number)!'};
2954 $c->detach();
2956 $user_id = $user_info[0];
2957 $user_role = $user_info[1];
2958 my $p = CXGN::People::Person->new($dbh, $user_id);
2959 $user_name = $p->get_username;
2960 } else{
2961 if (!$c->user){
2962 $c->stash->{rest} = {error=>'You must be logged in to upload plot coordinates (row and column number)!'};
2963 $c->detach();
2965 $user_id = $c->user()->get_object()->get_sp_person_id();
2966 $user_name = $c->user()->get_object()->get_username();
2967 $user_role = $c->user->get_object->get_user_type();
2970 if ($user_role ne 'curator' && $user_role ne 'submitter') {
2971 $c->stash->{rest} = {error => "You have insufficient privileges to add coordinates (row and column numbers)." };
2972 $c->detach();
2975 my $time = DateTime->now();
2976 my $timestamp = $time->ymd()."_".$time->hms();
2977 my $subdirectory = 'trial_coords_upload';
2978 my $upload = $c->req->upload('trial_coordinates_uploaded_file');
2979 my $trial_id = $c->req->param('trial_coordinates_upload_trial_id');
2980 my $upload_tempfile = $upload->tempname;
2981 my $upload_original_name = $upload->filename();
2982 my $md5;
2983 my %upload_metadata;
2985 # Store uploaded temporary file in archive
2986 print STDERR "TEMP FILE: $upload_tempfile\n";
2987 my $uploader = CXGN::UploadFile->new({
2988 tempfile => $upload_tempfile,
2989 subdirectory => $subdirectory,
2990 archive_path => $c->config->{archive_path},
2991 archive_filename => $upload_original_name,
2992 timestamp => $timestamp,
2993 user_id => $user_id,
2994 user_role => $user_role
2996 my $archived_filename_with_path = $uploader->archive();
2998 if (!$archived_filename_with_path) {
2999 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
3000 return;
3003 $md5 = $uploader->get_md5($archived_filename_with_path);
3004 unlink $upload_tempfile;
3006 my $error_string = '';
3007 # open file and remove return of line
3008 open(my $F, "< :encoding(UTF-8)", $archived_filename_with_path) || die "Can't open archive file $archived_filename_with_path";
3009 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3010 my $header = <$F>;
3011 while (<$F>) {
3012 chomp;
3013 $_ =~ s/\r//g;
3014 my ($plot,$row,$col) = split /\t/ ;
3015 my $rs = $schema->resultset("Stock::Stock")->search({uniquename=> $plot });
3016 if ($rs->count()== 1) {
3017 my $r = $rs->first();
3018 print STDERR "The plots $plot was found.\n Loading row $row col $col\n";
3019 $r->create_stockprops({row_number => $row, col_number => $col});
3021 else {
3022 print STDERR "WARNING! $plot was not found in the database.\n";
3023 $error_string .= "WARNING! $plot was not found in the database.";
3027 if ($error_string){
3028 $c->stash->{rest} = {error_string => $error_string};
3029 $c->detach();
3032 my $dbh = $c->dbc->dbh();
3033 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
3034 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'phenotypes', 'concurrent', $c->config->{basepath});
3035 my $trial_layout = CXGN::Trial::TrialLayout->new({ schema => $c->dbic_schema("Bio::Chado::Schema"), trial_id => $trial_id, experiment_type => 'field_layout' });
3036 $trial_layout->generate_and_cache_layout();
3038 $c->stash->{rest} = {success => 1};
3041 sub crosses_in_crossingtrial : Chained('trial') PathPart('crosses_in_crossingtrial') Args(0) {
3042 my $self = shift;
3043 my $c = shift;
3044 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3046 my $trial_id = $c->stash->{trial_id};
3047 my $trial = CXGN::Cross->new({schema => $schema, trial_id => $trial_id});
3049 my $result = $trial->get_crosses_in_crossing_experiment();
3050 my @crosses;
3051 foreach my $r (@$result){
3052 my ($cross_id, $cross_name) =@$r;
3053 push @crosses, {
3054 cross_id => $cross_id,
3055 cross_name => $cross_name,
3059 $c->stash->{rest} = { data => \@crosses };
3062 sub crosses_and_details_in_trial : Chained('trial') PathPart('crosses_and_details_in_trial') Args(0) {
3063 my $self = shift;
3064 my $c = shift;
3065 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3067 my $trial_id = $c->stash->{trial_id};
3068 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3070 my $result = $trial->get_crosses_and_details_in_crossingtrial();
3071 my @crosses;
3072 foreach my $r (@$result){
3073 my ($cross_id, $cross_name, $cross_combination, $cross_type, $female_parent_id, $female_parent_name, $female_ploidy, $male_parent_id, $male_parent_name, $male_ploidy, $female_plot_id, $female_plot_name, $male_plot_id, $male_plot_name, $female_plant_id, $female_plant_name, $male_plant_id, $male_plant_name) =@$r;
3074 push @crosses, {
3075 cross_id => $cross_id,
3076 cross_name => $cross_name,
3077 cross_combination => $cross_combination,
3078 cross_type => $cross_type,
3079 female_parent_id => $female_parent_id,
3080 female_parent_name => $female_parent_name,
3081 female_ploidy_level => $female_ploidy,
3082 male_parent_id => $male_parent_id,
3083 male_parent_name => $male_parent_name,
3084 male_ploidy_level => $male_ploidy,
3085 female_plot_id => $female_plot_id,
3086 female_plot_name => $female_plot_name,
3087 male_plot_id => $male_plot_id,
3088 male_plot_name => $male_plot_name,
3089 female_plant_id => $female_plant_id,
3090 female_plant_name => $female_plant_name,
3091 male_plant_id => $male_plant_id,
3092 male_plant_name => $male_plant_name
3096 $c->stash->{rest} = { data => \@crosses };
3099 sub cross_properties_trial : Chained('trial') PathPart('cross_properties_trial') Args(0) {
3100 my $self = shift;
3101 my $c = shift;
3102 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3104 my $trial_id = $c->stash->{trial_id};
3105 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3107 my $result = $trial->get_cross_properties_trial();
3109 my $cross_properties = $c->config->{cross_properties};
3110 my @column_order = split ',', $cross_properties;
3112 my @crosses;
3113 foreach my $r (@$result){
3114 my ($cross_id, $cross_name, $cross_combination, $cross_props_hash) =@$r;
3116 my @row = ( qq{<a href = "/cross/$cross_id">$cross_name</a>}, $cross_combination );
3117 foreach my $key (@column_order){
3118 push @row, $cross_props_hash->{$key};
3121 push @crosses, \@row;
3124 $c->stash->{rest} = { data => \@crosses };
3127 sub cross_progenies_trial : Chained('trial') PathPart('cross_progenies_trial') Args(0) {
3128 my $self = shift;
3129 my $c = shift;
3130 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3132 my $trial_id = $c->stash->{trial_id};
3133 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3135 my $result = $trial->get_cross_progenies_trial();
3136 my @crosses;
3137 foreach my $r (@$result){
3138 my ($cross_id, $cross_name, $cross_combination, $family_id, $family_name, $progeny_number) =@$r;
3139 push @crosses, [qq{<a href = "/cross/$cross_id">$cross_name</a>}, $cross_combination, $progeny_number, qq{<a href = "/family/$family_id/">$family_name</a>}];
3142 $c->stash->{rest} = { data => \@crosses };
3146 sub seedlots_from_crossingtrial : Chained('trial') PathPart('seedlots_from_crossingtrial') Args(0) {
3147 my $self = shift;
3148 my $c = shift;
3149 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3151 my $trial_id = $c->stash->{trial_id};
3152 my $trial = CXGN::Cross->new({schema => $schema, trial_id => $trial_id});
3154 my $result = $trial->get_seedlots_from_crossingtrial();
3155 my @crosses;
3156 foreach my $r (@$result){
3157 my ($cross_id, $cross_name, $seedlot_id, $seedlot_name) =@$r;
3158 push @crosses, {
3159 cross_id => $cross_id,
3160 cross_name => $cross_name,
3161 seedlot_id => $seedlot_id,
3162 seedlot_name => $seedlot_name
3166 $c->stash->{rest} = { data => \@crosses };
3171 sub get_crosses : Chained('trial') PathPart('get_crosses') Args(0) {
3172 my $self = shift;
3173 my $c = shift;
3174 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3176 my $trial_id = $c->stash->{trial_id};
3177 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3179 my $result = $trial->get_crosses_in_crossing_experiment();
3180 my @data = @$result;
3181 # print STDERR "CROSSES =".Dumper(\@data)."\n";
3183 $c->stash->{rest} = { crosses => \@data };
3187 sub get_female_accessions : Chained('trial') PathPart('get_female_accessions') Args(0) {
3188 my $self = shift;
3189 my $c = shift;
3190 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3192 my $trial_id = $c->stash->{trial_id};
3193 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3195 my $result = $trial->get_female_accessions_in_crossing_experiment();
3196 my @data = @$result;
3197 # print STDERR "FEMALE ACCESSIONS =".Dumper(\@data)."\n";
3199 $c->stash->{rest} = { female_accessions => \@data };
3203 sub get_male_accessions : Chained('trial') PathPart('get_male_accessions') Args(0) {
3204 my $self = shift;
3205 my $c = shift;
3206 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3208 my $trial_id = $c->stash->{trial_id};
3209 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3211 my $result = $trial->get_male_accessions_in_crossing_experiment();
3212 my @data = @$result;
3214 $c->stash->{rest} = { male_accessions => \@data };
3218 sub get_female_plots : Chained('trial') PathPart('get_female_plots') Args(0) {
3219 my $self = shift;
3220 my $c = shift;
3221 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3223 my $trial_id = $c->stash->{trial_id};
3224 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3226 my $result = $trial->get_female_plots_in_crossing_experiment();
3227 my @data = @$result;
3229 $c->stash->{rest} = { female_plots => \@data };
3233 sub get_male_plots : Chained('trial') PathPart('get_male_plots') Args(0) {
3234 my $self = shift;
3235 my $c = shift;
3236 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3238 my $trial_id = $c->stash->{trial_id};
3239 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3241 my $result = $trial->get_male_plots_in_crossing_experiment();
3242 my @data = @$result;
3244 $c->stash->{rest} = { male_plots => \@data };
3248 sub get_female_plants : Chained('trial') PathPart('get_female_plants') Args(0) {
3249 my $self = shift;
3250 my $c = shift;
3251 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3253 my $trial_id = $c->stash->{trial_id};
3254 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3256 my $result = $trial->get_female_plants_in_crossing_experiment();
3257 my @data = @$result;
3258 # print STDERR "FEMALE PLANTS =".Dumper(\@data)."\n";
3260 $c->stash->{rest} = { female_plants => \@data };
3264 sub get_male_plants : Chained('trial') PathPart('get_male_plants') Args(0) {
3265 my $self = shift;
3266 my $c = shift;
3267 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3269 my $trial_id = $c->stash->{trial_id};
3270 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3272 my $result = $trial->get_male_plants_in_crossing_experiment();
3273 my @data = @$result;
3275 $c->stash->{rest} = { male_plants => \@data };
3279 sub delete_all_crosses_in_crossingtrial : Chained('trial') PathPart('delete_all_crosses_in_crossingtrial') Args(0) {
3280 my $self = shift;
3281 my $c = shift;
3282 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3283 my $trial_id = $c->stash->{trial_id};
3285 if (!$c->user()){
3286 $c->stash->{rest} = { error => "You must be logged in to delete crosses" };
3287 $c->detach();
3289 if (!$c->user()->check_roles("curator")) {
3290 $c->stash->{rest} = { error => "You do not have the correct role to delete crosses. Please contact us." };
3291 $c->detach();
3294 my $trial = CXGN::Cross->new({schema => $schema, trial_id => $trial_id});
3296 my $result = $trial->get_crosses_in_crossing_experiment();
3298 foreach my $r (@$result){
3299 my ($cross_stock_id, $cross_name) =@$r;
3300 my $cross = CXGN::Cross->new( { schema => $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado'), cross_stock_id => $cross_stock_id });
3301 my $error = $cross->delete();
3302 print STDERR "ERROR = $error\n";
3304 if ($error) {
3305 $c->stash->{rest} = { error => "An error occurred attempting to delete a cross. ($@)" };
3306 return;
3310 $c->stash->{rest} = { success => 1 };
3314 sub cross_additional_info_trial : Chained('trial') PathPart('cross_additional_info_trial') Args(0) {
3315 my $self = shift;
3316 my $c = shift;
3317 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3319 my $trial_id = $c->stash->{trial_id};
3320 my $trial = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id});
3321 my $result = $trial->get_cross_additional_info_trial();
3322 # print STDERR "ADDITIONAL INFO =".Dumper($result)."\n";
3324 my $cross_additional_info_string = $c->config->{cross_additional_info};
3325 my @column_order = split ',', $cross_additional_info_string;
3327 my @crosses;
3328 foreach my $r (@$result){
3329 my ($cross_id, $cross_name, $cross_combination, $cross_additional_info_hash) =@$r;
3331 my @row = ( qq{<a href = "/cross/$cross_id">$cross_name</a>}, $cross_combination );
3332 foreach my $key (@column_order){
3333 push @row, $cross_additional_info_hash->{$key};
3336 push @crosses, \@row;
3339 $c->stash->{rest} = { data => \@crosses };
3343 sub downloaded_intercross_file_metadata : Chained('trial') PathPart('downloaded_intercross_file_metadata') Args(0) {
3344 my $self = shift;
3345 my $c = shift;
3346 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3348 my $trial_id = $c->stash->{trial_id};
3349 my $crosses = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id, file_type => 'intercross_download'});
3350 my $result = $crosses->get_intercross_file_metadata();
3352 $c->stash->{rest} = { data => $result };
3356 sub uploaded_intercross_file_metadata : Chained('trial') PathPart('uploaded_intercross_file_metadata') Args(0) {
3357 my $self = shift;
3358 my $c = shift;
3359 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3361 my $trial_id = $c->stash->{trial_id};
3362 my $crosses = CXGN::Cross->new({ schema => $schema, trial_id => $trial_id, file_type => 'intercross_upload'});
3363 my $result = $crosses->get_intercross_file_metadata();
3365 $c->stash->{rest} = { data => $result };
3369 sub phenotype_heatmap : Chained('trial') PathPart('heatmap') Args(0) {
3370 my $self = shift;
3371 my $c = shift;
3372 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
3373 my $trial_id = $c->stash->{trial_id};
3374 my $trait_id = $c->req->param("selected");
3376 my @items = map {@{$_}[0]} @{$c->stash->{trial}->get_plots()};
3377 #print STDERR Dumper(\@items);
3378 my @trait_ids = ($trait_id);
3380 my $layout = $c->stash->{trial_layout};
3381 my $design_type = $layout->get_design_type();
3383 my $phenotypes_search = CXGN::Phenotypes::SearchFactory->instantiate(
3384 "Native",
3386 bcs_schema=> $schema,
3387 data_level=> 'plot',
3388 trait_list=> \@trait_ids,
3389 plot_list=> \@items,
3392 my $data = $phenotypes_search->search();
3393 my (@col_No, @row_No, @pheno_val, @plot_Name, @stock_Name, @plot_No, @block_No, @rep_No, @msg, $result, @phenoID);
3394 foreach my $d (@$data) {
3395 my $stock_id = $d->{accession_stock_id};
3396 my $stock_name = $d->{accession_uniquename};
3397 my $value = $d->{phenotype_value};
3398 my $plot_id = $d->{obsunit_stock_id};
3399 my $plot_name = $d->{obsunit_uniquename};
3400 my $rep = $d->{rep};
3401 my $block_number = $d->{block};
3402 my $plot_number = $d->{plot_number};
3403 my $row_number = $d->{row_number};
3404 my $col_number = $d->{col_number};
3405 my $design = $d->{design};
3406 my $phenotype_id = $d->{phenotype_id};
3407 if (!$row_number && !$col_number){
3408 if ($block_number && $design_type ne 'splitplot'){
3409 $row_number = $block_number;
3410 }elsif ($rep && !$block_number && $design_type ne 'splitplot'){
3411 $row_number = $rep;
3412 }elsif ($design_type eq 'splitplot'){
3413 $row_number = $rep;
3417 my $plot_popUp = $plot_name."\nplot_No:".$plot_number."\nblock_No:".$block_number."\nrep_No:".$rep."\nstock:".$stock_name."\nvalue:".$value;
3418 push @$result, {plotname => $plot_name, stock => $stock_name, plotn => $plot_number, blkn=>$block_number, rep=>$rep, row=>$row_number, col=>$col_number, pheno=>$value, plot_msg=>$plot_popUp, pheno_id=>$phenotype_id} ;
3419 if ($col_number){
3420 push @col_No, $col_number;
3422 push @row_No, $row_number;
3423 push @pheno_val, $value;
3424 push @plot_Name, $plot_name;
3425 push @stock_Name, $stock_name;
3426 push @plot_No, $plot_number;
3427 push @block_No, $block_number;
3428 push @rep_No, $rep;
3429 push @phenoID, $phenotype_id;
3432 my $false_coord;
3433 if (!$col_No[0]){
3434 @col_No = ();
3435 $false_coord = 'false_coord';
3436 my @row_instances = uniq @row_No;
3437 my %unique_row_counts;
3438 $unique_row_counts{$_}++ for @row_No;
3439 my @col_number2;
3440 for my $key (keys %unique_row_counts){
3441 push @col_number2, (1..$unique_row_counts{$key});
3443 for (my $i=0; $i < scalar(@$result); $i++){
3444 @$result[$i]->{'col'} = $col_number2[$i];
3445 push @col_No, $col_number2[$i];
3449 my ($min_col, $max_col) = minmax @col_No;
3450 my ($min_row, $max_row) = minmax @row_No;
3451 my (@unique_col,@unique_row);
3452 for my $x (1..$max_col){
3453 push @unique_col, $x;
3455 for my $y (1..$max_row){
3456 push @unique_row, $y;
3459 my $trial = CXGN::Trial->new({
3460 bcs_schema => $schema,
3461 trial_id => $trial_id
3463 my $data_check = $trial->get_controls();
3464 my @control_name;
3465 foreach my $cntrl (@{$data_check}) {
3466 push @control_name, $cntrl->{'accession_name'};
3468 #print STDERR Dumper($result);
3469 $c->stash->{rest} = { #phenotypes => $phenotype,
3470 col => \@col_No,
3471 row => \@row_No,
3472 pheno => \@pheno_val,
3473 plotName => \@plot_Name,
3474 stock => \@stock_Name,
3475 plot => \@plot_No,
3476 block => \@block_No,
3477 rep => \@rep_No,
3478 result => $result,
3479 plot_msg => \@msg,
3480 col_max => $max_col,
3481 row_max => $max_row,
3482 unique_col => \@unique_col,
3483 unique_row => \@unique_row,
3484 false_coord => $false_coord,
3485 phenoID => \@phenoID,
3486 controls => \@control_name
3490 sub get_suppress_plot_phenotype : Chained('trial') PathPart('suppress_phenotype') Args(0) {
3491 my $self = shift;
3492 my $c = shift;
3493 my $schema = $c->dbic_schema('Bio::Chado::Schema');
3494 my $plot_name = $c->req->param('plot_name');
3495 my $plot_pheno_value = $c->req->param('phenotype_value');
3496 my $trait_id = $c->req->param('trait_id');
3497 my $phenotype_id = $c->req->param('phenotype_id');
3498 my $trial_id = $c->stash->{trial_id};
3499 my $trial = $c->stash->{trial};
3500 my $user_name = $c->user()->get_object()->get_username();
3501 my $time = DateTime->now();
3502 my $timestamp = $time->ymd()."_".$time->hms();
3504 if ($self->privileges_denied($c)) {
3505 $c->stash->{rest} = { error => "You have insufficient access privileges to suppress this phenotype." };
3506 return;
3509 my $suppress_return_error = $trial->suppress_plot_phenotype($trait_id, $plot_name, $plot_pheno_value, $phenotype_id, $user_name, $timestamp);
3510 if ($suppress_return_error) {
3511 $c->stash->{rest} = { error => $suppress_return_error };
3512 return;
3515 $c->stash->{rest} = { success => 1};
3518 sub delete_single_assayed_trait : Chained('trial') PathPart('delete_single_trait') Args(0) {
3519 my $self = shift;
3520 my $c = shift;
3521 my $pheno_ids = $c->req->param('pheno_id') ? JSON::decode_json($c->req->param('pheno_id')) : [];
3522 my $trait_ids = $c->req->param('traits_id') ? JSON::decode_json($c->req->param('traits_id')) : [];
3523 my $schema = $c->dbic_schema('Bio::Chado::Schema');
3524 my $trial = $c->stash->{trial};
3526 if (!$c->user()) {
3527 print STDERR "User not logged in... not deleting trait.\n";
3528 $c->stash->{rest} = {error => "You need to be logged in to delete trait." };
3529 return;
3532 if ($self->privileges_denied($c)) {
3533 $c->stash->{rest} = { error => "You have insufficient access privileges to delete assayed trait for this trial." };
3534 return;
3537 my $dir = $c->tempfiles_subdir('/delete_nd_experiment_ids');
3538 my $temp_file_nd_experiment_id = $c->config->{basepath}."/".$c->tempfile( TEMPLATE => 'delete_nd_experiment_ids/fileXXXX');
3539 my $delete_trait_return_error = $trial->delete_assayed_trait($c->config->{basepath}, $c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, $temp_file_nd_experiment_id, $pheno_ids, $trait_ids);
3541 if ($delete_trait_return_error) {
3542 $c->stash->{rest} = { error => $delete_trait_return_error };
3543 } else {
3544 $c->stash->{rest} = { success => 1};
3548 sub retrieve_plot_image : Chained('trial') PathPart('retrieve_plot_images') Args(0) {
3549 my $self = shift;
3550 my $c = shift;
3551 my $schema = $c->dbic_schema('Bio::Chado::Schema');
3552 my $image_ids = decode_json $c->req->param('image_ids');
3553 my $plot_name = $c->req->param('plot_name');
3554 my $plot_id = $c->req->param('plot_id');
3555 my $trial_id = $c->stash->{trial_id};
3556 my $stockref;
3557 my $image_objects;
3558 my $dbh = $c->dbc->dbh;
3559 $stockref->{dbh} = $dbh;
3560 $stockref->{image_ids} = $image_ids || [] ;
3561 my $images = $stockref->{image_ids};
3562 $dbh = $stockref->{dbh};
3564 #print STDERR Dumper($stockref);
3565 print "$plot_name and $plot_id and $image_ids\n";
3567 my $image_html = "";
3568 my $m_image_html = "";
3569 my $count;
3570 my @more_is;
3572 if ($images && !$image_objects) {
3573 my @image_object_list = map { SGN::Image->new( $dbh , $_ ) } @$images ;
3574 $image_objects = \@image_object_list;
3577 if ($image_objects) { # don't display anything for empty list of images
3578 $image_html .= qq|<table cellpadding="5">|;
3579 foreach my $image_ob (@$image_objects) {
3580 $count++;
3581 my $image_id = $image_ob->get_image_id;
3582 my $image_name = $image_ob->get_name();
3583 my $image_description = $image_ob->get_description();
3584 my $image_img = $image_ob->get_image_url("medium");
3585 my $small_image = $image_ob->get_image_url("thumbnail");
3586 my $image_page = "/image/view/$image_id";
3588 my $colorbox =
3589 qq|<a href="$image_img" class="stock_image_group" rel="gallery-figures"><img src="$small_image" alt="$image_description" onclick="close_view_plot_image_dialog()"/></a> |;
3590 my $fhtml =
3591 qq|<tr><td width=120>|
3592 . $colorbox
3593 . $image_name
3594 . "</td><td>"
3595 . $image_description
3596 . "</td></tr>";
3597 if ( $count < 3 ) { $image_html .= $fhtml; }
3598 else {
3599 push @more_is, $fhtml;
3600 } #more than 3 figures- show these in a hidden div
3602 $image_html .= "</table>"; #close the table tag or the first 3 figures
3604 $image_html .= "<script> jQuery(document).ready(function() { jQuery('a.stock_image_group').colorbox(); }); </script>\n";
3607 $m_image_html .=
3608 "<table cellpadding=5>"; #open table tag for the hidden figures #4 and on
3609 my $more = scalar(@more_is);
3610 foreach (@more_is) { $m_image_html .= $_; }
3612 $m_image_html .= "</table>"; #close tabletag for the hidden figures
3614 if (@more_is) { #html_optional_show if there are more than 3 figures
3615 $image_html .= html_optional_show(
3616 "Images",
3617 "<b>See $more more images...</b>",
3618 qq| $m_image_html |,
3619 0, #< do not show by default
3620 'abstract_optional_show', #< don't use the default button-like style
3624 $c->stash->{rest} = { image_html => $image_html};
3627 sub field_trial_from_field_trial : Chained('trial') PathPart('field_trial_from_field_trial') Args(0) {
3628 my $self = shift;
3629 my $c = shift;
3630 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3632 my $source_field_trials_for_this_trial = $c->stash->{trial}->get_field_trials_source_field_trials();
3633 my $field_trials_sourced_from_this_trial = $c->stash->{trial}->get_field_trials_sourced_from_field_trials();
3635 $c->stash->{rest} = {success => 1, source_field_trials => $source_field_trials_for_this_trial, field_trials_sourced => $field_trials_sourced_from_this_trial};
3638 sub genotyping_trial_from_field_trial : Chained('trial') PathPart('genotyping_trial_from_field_trial') Args(0) {
3639 my $self = shift;
3640 my $c = shift;
3641 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3643 my $genotyping_trials_from_field_trial = $c->stash->{trial}->get_genotyping_trials_from_field_trial();
3644 my $field_trials_source_of_genotyping_trial = $c->stash->{trial}->get_field_trials_source_of_genotyping_trial();
3646 $c->stash->{rest} = {success => 1, genotyping_trials_from_field_trial => $genotyping_trials_from_field_trial, field_trials_source_of_genotyping_trial => $field_trials_source_of_genotyping_trial};
3649 sub delete_genotyping_plate_from_field_trial_linkage : Chained('trial') PathPart('delete_genotyping_plate_from_field_trial_linkage') Args(1) {
3650 my $self = shift;
3651 my $c = shift;
3652 my $field_trial_id = shift;
3653 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3655 if (!$c->user) {
3656 $c->stash->{rest} = { error => "You must be logged in to remove genotyping plate and field trial linkage!" };
3657 $c->detach();
3660 my @roles = $c->user->roles();
3661 my $result = $c->stash->{trial}->delete_genotyping_plate_from_field_trial_linkage($field_trial_id, $roles[0]);
3663 if (exists($result->{errors})) {
3664 $c->stash->{rest} = { error => $result->{errors} };
3666 else {
3667 $c->stash->{rest} = { success => 1 };
3672 sub crossing_trial_from_field_trial : Chained('trial') PathPart('crossing_trial_from_field_trial') Args(0) {
3673 my $self = shift;
3674 my $c = shift;
3675 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3677 my $crossing_trials_from_field_trial = $c->stash->{trial}->get_crossing_trials_from_field_trial();
3678 my $field_trials_source_of_crossing_trial = $c->stash->{trial}->get_field_trials_source_of_crossing_trial();
3680 $c->stash->{rest} = {success => 1, crossing_trials_from_field_trial => $crossing_trials_from_field_trial, field_trials_source_of_crossing_trial => $field_trials_source_of_crossing_trial};
3683 sub trial_correlate_traits : Chained('trial') PathPart('correlate_traits') Args(0) {
3684 my $self = shift;
3685 my $c = shift;
3686 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3687 my $trait_ids = decode_json $c->req->param('trait_ids');
3688 my $obsunit_level = $c->req->param('observation_unit_level');
3689 my $correlation_type = $c->req->param('correlation_type');
3691 my $user_id;
3692 my $user_name;
3693 my $user_role;
3694 my $session_id = $c->req->param("sgn_session_id");
3696 if ($session_id){
3697 my $dbh = $c->dbc->dbh;
3698 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
3699 if (!$user_info[0]){
3700 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
3701 $c->detach();
3703 $user_id = $user_info[0];
3704 $user_role = $user_info[1];
3705 my $p = CXGN::People::Person->new($dbh, $user_id);
3706 $user_name = $p->get_username;
3707 } else{
3708 if (!$c->user){
3709 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
3710 $c->detach();
3712 $user_id = $c->user()->get_object()->get_sp_person_id();
3713 $user_name = $c->user()->get_object()->get_username();
3714 $user_role = $c->user->get_object->get_user_type();
3717 my $phenotypes_search = CXGN::Phenotypes::SearchFactory->instantiate(
3718 'MaterializedViewTable',
3720 bcs_schema=>$schema,
3721 data_level=>$obsunit_level,
3722 trait_list=>$trait_ids,
3723 trial_list=>[$c->stash->{trial_id}],
3724 include_timestamp=>0,
3725 exclude_phenotype_outlier=>0
3728 my ($data, $unique_traits) = $phenotypes_search->search();
3729 my @sorted_trait_names = sort keys %$unique_traits;
3731 if (scalar(@$data) == 0) {
3732 $c->stash->{rest} = { error => "There are no phenotypes for the trials and traits you have selected!"};
3733 return;
3736 my %phenotype_data;
3737 my %trait_hash;
3738 my %seen_obsunit_ids;
3739 foreach my $obs_unit (@$data){
3740 my $obsunit_id = $obs_unit->{observationunit_stock_id};
3741 my $observations = $obs_unit->{observations};
3742 foreach (@$observations){
3743 $phenotype_data{$obsunit_id}->{$_->{trait_id}} = $_->{value};
3744 $trait_hash{$_->{trait_id}} = $_->{trait_name};
3746 $seen_obsunit_ids{$obsunit_id}++;
3748 my @sorted_obs_units = sort keys %seen_obsunit_ids;
3750 my $header_string = join ',', @$trait_ids;
3752 my $shared_cluster_dir_config = $c->config->{cluster_shared_tempdir};
3753 my $tmp_stats_dir = $shared_cluster_dir_config."/tmp_trial_correlation";
3754 mkdir $tmp_stats_dir if ! -d $tmp_stats_dir;
3755 my ($stats_tempfile_fh, $stats_tempfile) = tempfile("drone_stats_XXXXX", DIR=> $tmp_stats_dir);
3756 my ($stats_out_tempfile_fh, $stats_out_tempfile) = tempfile("drone_stats_XXXXX", DIR=> $tmp_stats_dir);
3758 open(my $F, ">", $stats_tempfile) || die "Can't open file ".$stats_tempfile;
3759 print $F $header_string."\n";
3760 foreach my $s (@sorted_obs_units) {
3761 my @line = ();
3762 foreach my $t (@$trait_ids) {
3763 my $val = $phenotype_data{$s}->{$t};
3764 if (!$val && $val != 0) {
3765 $val = 'NA';
3767 push @line, $val;
3769 my $line_string = join ',', @line;
3770 print $F "$line_string\n";
3772 close($F);
3774 my $cmd = 'R -e "library(data.table);
3775 mat <- fread(\''.$stats_tempfile.'\', header=TRUE, sep=\',\');
3776 res <- cor(mat, method=\''.$correlation_type.'\', use = \'complete.obs\')
3777 res_rounded <- round(res, 2)
3778 write.table(res_rounded, file=\''.$stats_out_tempfile.'\', row.names=TRUE, col.names=TRUE, sep=\'\t\');"';
3779 print STDERR Dumper $cmd;
3780 my $status = system($cmd);
3782 my $csv = Text::CSV->new({ sep_char => "\t" });
3783 my @result;
3784 open(my $fh, '<', $stats_out_tempfile)
3785 or die "Could not open file '$stats_out_tempfile' $!";
3787 print STDERR "Opened $stats_out_tempfile\n";
3788 my $header = <$fh>;
3789 my @header_cols;
3790 if ($csv->parse($header)) {
3791 @header_cols = $csv->fields();
3794 my @header_trait_names = ("Trait");
3795 foreach (@header_cols) {
3796 push @header_trait_names, $trait_hash{$_};
3798 push @result, \@header_trait_names;
3800 while (my $row = <$fh>) {
3801 my @columns;
3802 if ($csv->parse($row)) {
3803 @columns = $csv->fields();
3806 my $trait_id = shift @columns;
3807 my @line = ($trait_hash{$trait_id});
3808 push @line, @columns;
3809 push @result, \@line;
3811 close($fh);
3813 $c->stash->{rest} = {success => 1, result => \@result};
3816 sub trial_plot_time_series_accessions : Chained('trial') PathPart('plot_time_series_accessions') Args(0) {
3817 my $self = shift;
3818 my $c = shift;
3819 my $schema = $c->dbic_schema("Bio::Chado::Schema");
3820 my $trait_ids = decode_json $c->req->param('trait_ids');
3821 my $accession_ids = $c->req->param('accession_ids') ne 'null' ? decode_json $c->req->param('accession_ids') : [];
3822 my $trait_format = $c->req->param('trait_format');
3823 my $data_level = $c->req->param('data_level');
3824 my $draw_error_bars = $c->req->param('draw_error_bars');
3825 my $use_cumulative_phenotype = $c->req->param('use_cumulative_phenotype');
3827 my $user_id;
3828 my $user_name;
3829 my $user_role;
3830 my $session_id = $c->req->param("sgn_session_id");
3832 if ($session_id){
3833 my $dbh = $c->dbc->dbh;
3834 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
3835 if (!$user_info[0]){
3836 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
3837 $c->detach();
3839 $user_id = $user_info[0];
3840 $user_role = $user_info[1];
3841 my $p = CXGN::People::Person->new($dbh, $user_id);
3842 $user_name = $p->get_username;
3843 } else{
3844 if (!$c->user){
3845 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
3846 $c->detach();
3848 $user_id = $c->user()->get_object()->get_sp_person_id();
3849 $user_name = $c->user()->get_object()->get_username();
3850 $user_role = $c->user->get_object->get_user_type();
3853 my $phenotypes_search = CXGN::Phenotypes::SearchFactory->instantiate(
3854 'MaterializedViewTable',
3856 bcs_schema=>$schema,
3857 data_level=>$data_level,
3858 trait_list=>$trait_ids,
3859 trial_list=>[$c->stash->{trial_id}],
3860 accession_list=>$accession_ids,
3861 include_timestamp=>0,
3862 exclude_phenotype_outlier=>0
3865 my ($data, $unique_traits) = $phenotypes_search->search();
3866 my @sorted_trait_names = sort keys %$unique_traits;
3868 if (scalar(@$data) == 0) {
3869 $c->stash->{rest} = { error => "There are no phenotypes for the trials and traits you have selected!"};
3870 return;
3873 my %trait_ids_hash = map {$_ => 1} @$trait_ids;
3875 my $trial = CXGN::Trial->new({bcs_schema=>$schema, trial_id=>$c->stash->{trial_id}});
3876 my $traits_assayed = $trial->get_traits_assayed($data_level, $trait_format, 'time_ontology');
3877 my %unique_traits_ids;
3878 foreach (@$traits_assayed) {
3879 if (exists($trait_ids_hash{$_->[0]})) {
3880 $unique_traits_ids{$_->[0]} = $_;
3883 my %unique_components;
3884 foreach (values %unique_traits_ids) {
3885 foreach my $component (@{$_->[2]}) {
3886 if ($component->{cv_type} && $component->{cv_type} eq 'time_ontology') {
3887 $unique_components{$_->[0]} = $component->{name};
3892 my @sorted_times;
3893 my %sorted_time_hash;
3894 while( my($trait_id, $time_name) = each %unique_components) {
3895 my @time_split = split ' ', $time_name;
3896 my $time_val = $time_split[1] + 0;
3897 push @sorted_times, $time_val;
3898 $sorted_time_hash{$time_val} = $trait_id;
3900 @sorted_times = sort @sorted_times;
3902 my %cumulative_time_hash;
3903 while( my($trait_id, $time_name) = each %unique_components) {
3904 my @time_split = split ' ', $time_name;
3905 my $time_val = $time_split[1] + 0;
3906 foreach my $t (@sorted_times) {
3907 if ($t < $time_val) {
3908 push @{$cumulative_time_hash{$time_val}}, $sorted_time_hash{$t};
3913 my %phenotype_data;
3914 my %trait_hash;
3915 my %seen_germplasm_names;
3916 foreach my $obs_unit (@$data){
3917 my $obsunit_id = $obs_unit->{observationunit_stock_id};
3918 my $observations = $obs_unit->{observations};
3919 my $germplasm_stock_id = $obs_unit->{germplasm_stock_id};
3920 my $germplasm_uniquename = $obs_unit->{germplasm_uniquename};
3921 foreach (@$observations){
3922 push @{$phenotype_data{$germplasm_uniquename}->{$_->{trait_id}}}, $_->{value};
3923 $trait_hash{$_->{trait_id}} = $_->{trait_name};
3925 $seen_germplasm_names{$germplasm_uniquename}++;
3927 my @sorted_germplasm_names = sort keys %seen_germplasm_names;
3929 my $header_string = 'germplasmName,time,value,sd';
3931 my $dir = $c->tempfiles_subdir('/trial_analysis_accession_time_series_plot_dir');
3932 my $pheno_data_tempfile_string = $c->tempfile( TEMPLATE => 'trial_analysis_accession_time_series_plot_dir/datafileXXXX');
3933 $pheno_data_tempfile_string .= '.csv';
3934 my $stats_tempfile = $c->config->{basepath}."/".$pheno_data_tempfile_string;
3936 open(my $F, ">", $stats_tempfile) || die "Can't open file ".$stats_tempfile;
3937 print $F $header_string."\n";
3938 foreach my $s (@sorted_germplasm_names) {
3939 foreach my $t (@$trait_ids) {
3940 my $time = $unique_components{$t};
3941 my @time_split = split ' ', $time;
3942 my $time_val = $time_split[1];
3943 my $vals = $phenotype_data{$s}->{$t};
3944 my $val;
3945 my $sd;
3946 if (!$vals || scalar(@$vals) == 0) {
3947 $val = 'NA';
3948 $sd = 0;
3950 else {
3951 my $stat = Statistics::Descriptive::Full->new();
3952 $stat->add_data(@$vals);
3953 $sd = $stat->standard_deviation();
3954 $val = $stat->mean();
3955 if ($use_cumulative_phenotype eq 'Yes') {
3956 my $previous_time_trait_ids = $cumulative_time_hash{$time_val};
3957 my @previous_vals_avgs = ($val);
3958 foreach my $pt (@$previous_time_trait_ids) {
3959 my $previous_vals = $phenotype_data{$s}->{$pt};
3960 my $previous_stat = Statistics::Descriptive::Full->new();
3961 $previous_stat->add_data(@$previous_vals);
3962 my $previous_val_avg = $previous_stat->mean();
3963 push @previous_vals_avgs, $previous_val_avg;
3965 my $stat_cumulative = Statistics::Descriptive::Full->new();
3966 $stat_cumulative->add_data(@previous_vals_avgs);
3967 $sd = $stat_cumulative->standard_deviation();
3968 $val = sum(@previous_vals_avgs);
3971 print $F "$s,$time_val,$val,$sd\n";
3974 close($F);
3976 my @set = ('0' ..'9', 'A' .. 'F');
3977 my @colors;
3978 for (1..scalar(@sorted_germplasm_names)) {
3979 my $str = join '' => map $set[rand @set], 1 .. 6;
3980 push @colors, '#'.$str;
3982 my $color_string = join '\',\'', @colors;
3984 my $pheno_figure_tempfile_string = $c->tempfile( TEMPLATE => 'trial_analysis_accession_time_series_plot_dir/figureXXXX');
3985 $pheno_figure_tempfile_string .= '.png';
3986 my $pheno_figure_tempfile = $c->config->{basepath}."/".$pheno_figure_tempfile_string;
3988 my $cmd = 'R -e "library(data.table); library(ggplot2);
3989 mat <- fread(\''.$stats_tempfile.'\', header=TRUE, sep=\',\');
3990 mat\$time <- as.numeric(as.character(mat\$time));
3991 options(device=\'png\');
3992 par();
3993 sp <- ggplot(mat, aes(x = time, y = value)) +
3994 geom_line(aes(color = germplasmName), size = 1) +
3995 scale_fill_manual(values = c(\''.$color_string.'\')) +
3996 theme_minimal()';
3997 if ($draw_error_bars eq "Yes") {
3998 $cmd .= '+ geom_errorbar(aes(ymin=value-sd, ymax=value+sd, color=germplasmName), width=.2, position=position_dodge(0.05));
4001 else {
4002 $cmd .= ';
4005 $cmd .= 'sp <- sp + guides(shape = guide_legend(override.aes = list(size = 0.5)));
4006 sp <- sp + guides(shape = guide_legend(override.aes = list(size = 0.5)));
4007 sp <- sp + guides(color = guide_legend(override.aes = list(size = 0.5)));
4008 sp <- sp + theme(legend.title = element_text(size = 3), legend.text = element_text(size = 3));';
4009 if (scalar(@sorted_germplasm_names) > 100) {
4010 $cmd .= 'sp <- sp + theme(legend.position = \'none\');';
4012 $cmd .= 'ggsave(\''.$pheno_figure_tempfile.'\', sp, device=\'png\', width=12, height=6, units=\'in\');
4013 dev.off();"';
4014 print STDERR Dumper $cmd;
4015 my $status = system($cmd);
4017 $c->stash->{rest} = {success => 1, figure => $pheno_figure_tempfile_string, data_file => $pheno_data_tempfile_string, cmd => $cmd};
4020 sub trial_accessions_rank : Chained('trial') PathPart('accessions_rank') Args(0) {
4021 my $self = shift;
4022 my $c = shift;
4023 my $schema = $c->dbic_schema("Bio::Chado::Schema");
4024 my $trait_ids = decode_json $c->req->param('trait_ids');
4025 my $trait_weights = decode_json $c->req->param('trait_weights');
4026 my $accession_ids = $c->req->param('accession_ids') ne 'null' ? decode_json $c->req->param('accession_ids') : [];
4027 my $trait_format = $c->req->param('trait_format');
4028 my $data_level = $c->req->param('data_level');
4030 my $user_id;
4031 my $user_name;
4032 my $user_role;
4033 my $session_id = $c->req->param("sgn_session_id");
4035 if ($session_id){
4036 my $dbh = $c->dbc->dbh;
4037 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
4038 if (!$user_info[0]){
4039 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
4040 $c->detach();
4042 $user_id = $user_info[0];
4043 $user_role = $user_info[1];
4044 my $p = CXGN::People::Person->new($dbh, $user_id);
4045 $user_name = $p->get_username;
4046 } else{
4047 if (!$c->user){
4048 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
4049 $c->detach();
4051 $user_id = $c->user()->get_object()->get_sp_person_id();
4052 $user_name = $c->user()->get_object()->get_username();
4053 $user_role = $c->user->get_object->get_user_type();
4056 my $phenotypes_search = CXGN::Phenotypes::SearchFactory->instantiate(
4057 'MaterializedViewTable',
4059 bcs_schema=>$schema,
4060 data_level=>$data_level,
4061 trait_list=>$trait_ids,
4062 trial_list=>[$c->stash->{trial_id}],
4063 accession_list=>$accession_ids,
4064 include_timestamp=>0,
4065 exclude_phenotype_outlier=>0
4068 my ($data, $unique_traits) = $phenotypes_search->search();
4069 my @sorted_trait_names = sort keys %$unique_traits;
4071 if (scalar(@$data) == 0) {
4072 $c->stash->{rest} = { error => "There are no phenotypes for the trials and traits you have selected!"};
4073 return;
4076 my %trait_weight_map;
4077 foreach (@$trait_weights) {
4078 $trait_weight_map{$_->[0]} = $_->[1];
4080 print STDERR Dumper \%trait_weight_map;
4082 my %phenotype_data;
4083 my %trait_hash;
4084 my %seen_germplasm_names;
4085 foreach my $obs_unit (@$data){
4086 my $obsunit_id = $obs_unit->{observationunit_stock_id};
4087 my $observations = $obs_unit->{observations};
4088 my $germplasm_stock_id = $obs_unit->{germplasm_stock_id};
4089 my $germplasm_uniquename = $obs_unit->{germplasm_uniquename};
4090 foreach (@$observations){
4091 push @{$phenotype_data{$germplasm_uniquename}->{$_->{trait_id}}}, $_->{value};
4092 $trait_hash{$_->{trait_id}} = $_->{trait_name};
4094 $seen_germplasm_names{$germplasm_uniquename}++;
4096 my @sorted_germplasm_names = sort keys %seen_germplasm_names;
4098 my %accession_sum;
4099 foreach my $s (@sorted_germplasm_names) {
4100 foreach my $t (@$trait_ids) {
4101 my $vals = $phenotype_data{$s}->{$t};
4102 my $average_val = sum(@$vals)/scalar(@$vals);
4103 my $average_val_weighted = $average_val*$trait_weight_map{$t};
4104 $accession_sum{$s} += $average_val_weighted;
4108 my @sorted_accessions = sort { $accession_sum{$b} <=> $accession_sum{$a} } keys(%accession_sum);
4109 my @sorted_values = @accession_sum{@sorted_accessions};
4110 my @sorted_rank = (1..scalar(@sorted_accessions));
4112 $c->stash->{rest} = {success => 1, results => \%accession_sum, sorted_accessions => \@sorted_accessions, sorted_values => \@sorted_values, sorted_ranks => \@sorted_rank};
4115 sub trial_genotype_comparison : Chained('trial') PathPart('genotype_comparison') Args(0) {
4116 my $self = shift;
4117 my $c = shift;
4118 print STDERR Dumper $c->req->params();
4119 my $schema = $c->dbic_schema("Bio::Chado::Schema");
4120 my $people_schema = $c->dbic_schema("CXGN::People::Schema");
4121 my $trait_ids = decode_json $c->req->param('trait_ids');
4122 my $trait_weights = decode_json $c->req->param('trait_weights');
4123 my $accession_ids = $c->req->param('accession_ids') ne 'null' ? decode_json $c->req->param('accession_ids') : [];
4124 my $trait_format = $c->req->param('trait_format');
4125 my $nd_protocol_id = $c->req->param('nd_protocol_id');
4126 my $data_level = $c->req->param('data_level');
4127 my $genotype_filter_string = $c->req->param('genotype_filter');
4128 my $compute_from_parents = $c->req->param('compute_from_parents') eq 'yes' ? 1 : 0;
4130 my $user_id;
4131 my $user_name;
4132 my $user_role;
4133 my $session_id = $c->req->param("sgn_session_id");
4135 if ($session_id){
4136 my $dbh = $c->dbc->dbh;
4137 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
4138 if (!$user_info[0]){
4139 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
4140 $c->detach();
4142 $user_id = $user_info[0];
4143 $user_role = $user_info[1];
4144 my $p = CXGN::People::Person->new($dbh, $user_id);
4145 $user_name = $p->get_username;
4146 } else{
4147 if (!$c->user){
4148 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
4149 $c->detach();
4151 $user_id = $c->user()->get_object()->get_sp_person_id();
4152 $user_name = $c->user()->get_object()->get_username();
4153 $user_role = $c->user->get_object->get_user_type();
4156 my $phenotypes_search = CXGN::Phenotypes::SearchFactory->instantiate(
4157 'MaterializedViewTable',
4159 bcs_schema=>$schema,
4160 data_level=>$data_level,
4161 trait_list=>$trait_ids,
4162 trial_list=>[$c->stash->{trial_id}],
4163 accession_list=>$accession_ids,
4164 include_timestamp=>0,
4165 exclude_phenotype_outlier=>0
4168 my ($data, $unique_traits) = $phenotypes_search->search();
4169 my @sorted_trait_names = sort keys %$unique_traits;
4171 if (scalar(@$data) == 0) {
4172 $c->stash->{rest} = { error => "There are no phenotypes for the trials and traits you have selected!"};
4173 return;
4176 my %trait_weight_map;
4177 foreach (@$trait_weights) {
4178 $trait_weight_map{$_->[0]} = $_->[1];
4180 # print STDERR Dumper \%trait_weight_map;
4182 my %phenotype_data;
4183 my %trait_hash;
4184 my %seen_germplasm_names;
4185 my %seen_germplasm_ids;
4186 foreach my $obs_unit (@$data){
4187 my $obsunit_id = $obs_unit->{observationunit_stock_id};
4188 my $observations = $obs_unit->{observations};
4189 my $germplasm_stock_id = $obs_unit->{germplasm_stock_id};
4190 my $germplasm_uniquename = $obs_unit->{germplasm_uniquename};
4191 foreach (@$observations){
4192 push @{$phenotype_data{$germplasm_uniquename}->{$_->{trait_id}}}, $_->{value};
4193 $trait_hash{$_->{trait_id}} = $_->{trait_name};
4195 $seen_germplasm_names{$germplasm_uniquename} = $germplasm_stock_id;
4196 $seen_germplasm_ids{$germplasm_stock_id}++;
4198 my @sorted_germplasm_names = sort keys %seen_germplasm_names;
4199 my @sorted_germplasm_ids = sort keys %seen_germplasm_ids;
4201 my %accession_sum;
4202 foreach my $s (@sorted_germplasm_names) {
4203 foreach my $t (@$trait_ids) {
4204 my $vals = $phenotype_data{$s}->{$t};
4205 my $average_val = sum(@$vals)/scalar(@$vals);
4206 my $average_val_weighted = $average_val*$trait_weight_map{$t};
4207 $accession_sum{$s} += $average_val_weighted;
4211 my @sorted_accessions = sort { $accession_sum{$b} <=> $accession_sum{$a} } keys(%accession_sum);
4212 my @sorted_values = @accession_sum{@sorted_accessions};
4213 my $sort_increment = ceil(scalar(@sorted_accessions)/10)+0;
4214 # print STDERR Dumper $sort_increment;
4216 my $percentile_inc = $sort_increment/scalar(@sorted_accessions);
4218 my $acc_counter = 1;
4219 my $rank_counter = 1;
4220 my %rank_hash;
4221 my %rank_lookup;
4222 my %rank_percentile;
4223 foreach (@sorted_accessions) {
4224 print STDERR Dumper $acc_counter;
4225 if ($acc_counter >= $sort_increment) {
4226 $rank_counter++;
4227 $acc_counter = 0;
4229 my $stock_id = $seen_germplasm_names{$_};
4230 push @{$rank_hash{$rank_counter}}, $stock_id;
4231 $rank_lookup{$stock_id} = $rank_counter;
4232 my $percentile = $rank_counter*$percentile_inc;
4233 $rank_percentile{$rank_counter} = "Rank ".$rank_counter;
4234 $acc_counter++;
4237 my @sorted_rank_groups;
4238 foreach (@sorted_accessions) {
4239 my $stock_id = $seen_germplasm_names{$_};
4240 push @sorted_rank_groups, $rank_lookup{$stock_id};
4242 my @sorted_ranks = (1..scalar(@sorted_accessions));
4243 # print STDERR Dumper \%rank_hash;
4244 # print STDERR Dumper \%rank_lookup;
4246 my $geno = CXGN::Genotype::DownloadFactory->instantiate(
4247 'DosageMatrix', #can be either 'VCF' or 'DosageMatrix'
4249 bcs_schema=>$schema,
4250 people_schema=>$people_schema,
4251 cache_root_dir=>$c->config->{cache_file_path},
4252 accession_list=>\@sorted_germplasm_ids,
4253 trial_list=>[$c->stash->{trial_id}],
4254 protocol_id_list=>[$nd_protocol_id],
4255 compute_from_parents=>$compute_from_parents,
4258 my $file_handle = $geno->download(
4259 $c->config->{cluster_shared_tempdir},
4260 $c->config->{backend},
4261 $c->config->{cluster_host},
4262 $c->config->{'web_cluster_queue'},
4263 $c->config->{basepath}
4266 my %genotype_filter;
4267 if ($genotype_filter_string) {
4268 my @genos = split ',', $genotype_filter_string;
4269 %genotype_filter = map {$_ => 1} @genos;
4272 my %geno_rank_counter;
4273 my %geno_rank_seen_scores;
4274 my @marker_names;
4275 open my $geno_fh, "<&", $file_handle or die "Can't open output file: $!";
4276 my $header = <$geno_fh>;
4277 chomp($header);
4278 # print STDERR Dumper $header;
4279 my @header = split "\t", $header;
4280 my $header_dummy = shift @header;
4282 my $position = 0;
4283 while (my $row = <$geno_fh>) {
4284 chomp($row);
4285 if ($row) {
4286 # print STDERR Dumper $row;
4287 my @line = split "\t", $row;
4288 my $marker_name = shift @line;
4289 push @marker_names, $marker_name;
4290 my $counter = 0;
4291 foreach (@line) {
4292 if ( defined $_ && $_ ne '' && $_ ne 'NA') {
4293 my $rank = $rank_lookup{$header[$counter]};
4294 if (!$genotype_filter_string || exists($genotype_filter{$_})) {
4295 $geno_rank_counter{$rank}->{$position}->{$_}++;
4296 $geno_rank_seen_scores{$_}++;
4299 $counter++;
4301 $position++;
4304 close($geno_fh);
4305 # print STDERR Dumper \%geno_rank_counter;
4306 my @sorted_seen_scores = sort keys %geno_rank_seen_scores;
4308 my $shared_cluster_dir_config = $c->config->{cluster_shared_tempdir};
4309 my $tmp_stats_dir = $shared_cluster_dir_config."/tmp_trial_genotype_comparision";
4310 mkdir $tmp_stats_dir if ! -d $tmp_stats_dir;
4311 my ($stats_tempfile_fh, $stats_tempfile) = tempfile("drone_stats_XXXXX", DIR=> $tmp_stats_dir);
4313 my $header_string = 'Rank,Genotype,Marker,Count';
4315 open(my $F, ">", $stats_tempfile) || die "Can't open file ".$stats_tempfile;
4316 print $F $header_string."\n";
4317 while (my ($rank, $pos_o) = each %geno_rank_counter) {
4318 while (my ($position, $score_o) = each %$pos_o) {
4319 while (my ($score, $count) = each %$score_o) {
4320 print $F $rank_percentile{$rank}.",$score,$position,$count\n";
4324 close($F);
4326 my @set = ('0' ..'9', 'A' .. 'F');
4327 my @colors;
4328 for (1..scalar(@sorted_seen_scores)) {
4329 my $str = join '' => map $set[rand @set], 1 .. 6;
4330 push @colors, '#'.$str;
4332 my $color_string = join '\',\'', @colors;
4334 my $dir = $c->tempfiles_subdir('/trial_analysis_genotype_comparision_plot_dir');
4335 my $pheno_figure_tempfile_string = $c->tempfile( TEMPLATE => 'trial_analysis_genotype_comparision_plot_dir/figureXXXX');
4336 $pheno_figure_tempfile_string .= '.png';
4337 my $pheno_figure_tempfile = $c->config->{basepath}."/".$pheno_figure_tempfile_string;
4339 my $cmd = 'R -e "library(data.table); library(ggplot2);
4340 mat <- fread(\''.$stats_tempfile.'\', header=TRUE, sep=\',\');
4341 mat\$Marker <- as.numeric(as.character(mat\$Marker));
4342 mat\$Genotype <- as.character(mat\$Genotype);
4343 options(device=\'png\');
4344 par();
4345 sp <- ggplot(mat, aes(x = Marker, y = Count)) +
4346 geom_line(aes(color = Genotype), size=0.2) +
4347 scale_fill_manual(values = c(\''.$color_string.'\')) +
4348 theme_minimal();
4349 sp <- sp + facet_grid(Rank ~ .);';
4350 $cmd .= 'ggsave(\''.$pheno_figure_tempfile.'\', sp, device=\'png\', width=12, height=12, units=\'in\');
4351 dev.off();"';
4352 print STDERR Dumper $cmd;
4353 my $status = system($cmd);
4355 $c->stash->{rest} = {success => 1, results => \%accession_sum, sorted_accessions => \@sorted_accessions, sorted_values => \@sorted_values, sorted_ranks => \@sorted_ranks, sorted_rank_groups => \@sorted_rank_groups, figure => $pheno_figure_tempfile_string};
4358 sub trial_calculate_numerical_derivative : Chained('trial') PathPart('calculate_numerical_derivative') Args(0) {
4359 my $self = shift;
4360 my $c = shift;
4361 my $schema = $c->dbic_schema("Bio::Chado::Schema");
4362 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
4363 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
4364 my $trait_ids = decode_json $c->req->param('trait_ids');
4365 my $derivative = $c->req->param('derivative');
4366 my $data_level = $c->req->param('data_level');
4368 my $user_id;
4369 my $user_name;
4370 my $user_role;
4371 my $session_id = $c->req->param("sgn_session_id");
4373 if ($session_id){
4374 my $dbh = $c->dbc->dbh;
4375 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
4376 if (!$user_info[0]){
4377 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
4378 $c->detach();
4380 $user_id = $user_info[0];
4381 $user_role = $user_info[1];
4382 my $p = CXGN::People::Person->new($dbh, $user_id);
4383 $user_name = $p->get_username;
4384 } else{
4385 if (!$c->user){
4386 $c->stash->{rest} = {error=>'You must be logged in to do this analysis!'};
4387 $c->detach();
4389 $user_id = $c->user()->get_object()->get_sp_person_id();
4390 $user_name = $c->user()->get_object()->get_username();
4391 $user_role = $c->user->get_object->get_user_type();
4394 my $phenotypes_search = CXGN::Phenotypes::SearchFactory->instantiate(
4395 'MaterializedViewTable',
4397 bcs_schema=>$schema,
4398 data_level=>$data_level,
4399 trait_list=>$trait_ids,
4400 trial_list=>[$c->stash->{trial_id}],
4401 include_timestamp=>0,
4402 exclude_phenotype_outlier=>0
4405 my ($data, $unique_traits) = $phenotypes_search->search();
4406 my @sorted_trait_names = sort keys %$unique_traits;
4408 if (scalar(@$data) == 0) {
4409 $c->stash->{rest} = { error => "There are no phenotypes for the trials and traits you have selected!"};
4410 return;
4413 my %phenotype_data;
4414 my %seen_plot_names;
4415 my %seen_rows;
4416 my %seen_cols;
4417 my %row_col_hash;
4418 my %rev_row;
4419 my %rev_col;
4420 foreach my $obs_unit (@$data){
4421 my $obsunit_id = $obs_unit->{observationunit_stock_id};
4422 my $obsunit_name = $obs_unit->{observationunit_uniquename};
4423 my $observations = $obs_unit->{observations};
4424 my $germplasm_stock_id = $obs_unit->{germplasm_stock_id};
4425 my $germplasm_uniquename = $obs_unit->{germplasm_uniquename};
4426 my $row = $obs_unit->{obsunit_row_number};
4427 my $col = $obs_unit->{obsunit_col_number};
4428 foreach (@$observations){
4429 $phenotype_data{$obsunit_name}->{$_->{trait_name}} = $_->{value};
4431 $rev_row{$obsunit_name} = $row;
4432 $rev_col{$obsunit_name} = $col;
4433 $row_col_hash{$row}->{$col} = $obsunit_name;
4434 $seen_plot_names{$obsunit_name}++;
4435 $seen_rows{$row}++;
4436 $seen_cols{$col}++;
4438 my @sorted_plot_names = sort keys %seen_plot_names;
4439 my @sorted_rows = sort { $a <=> $b } keys %seen_rows;
4440 my @sorted_cols = sort { $a <=> $b } keys %seen_cols;
4442 my @allowed_composed_cvs = split ',', $c->config->{composable_cvs};
4443 my $composable_cvterm_delimiter = $c->config->{composable_cvterm_delimiter};
4444 my $composable_cvterm_format = $c->config->{composable_cvterm_format};
4446 my %trait_id_map;
4447 foreach my $trait_name (@sorted_trait_names) {
4448 my $trait_cvterm_id = SGN::Model::Cvterm->get_cvterm_row_from_trait_name($schema, $trait_name)->cvterm_id();
4449 $trait_id_map{$trait_name} = $trait_cvterm_id;
4451 my @trait_ids = values %trait_id_map;
4453 my $analysis_statistical_ontology_term = 'Two-dimension numerical first derivative across rows and columns|SGNSTAT:0000022';
4454 # my $analysis_statistical_ontology_term = 'Two-dimension numerical second derivative across rows and columns|SGNSTAT:0000023';
4455 my $stat_cvterm_id = SGN::Model::Cvterm->get_cvterm_row_from_trait_name($schema, $analysis_statistical_ontology_term)->cvterm_id();
4457 my $categories = {
4458 object => [],
4459 attribute => [$stat_cvterm_id],
4460 method => [],
4461 unit => [],
4462 trait => \@trait_ids,
4463 tod => [],
4464 toy => [],
4465 gen => [],
4468 my %time_term_map;
4470 my $traits = SGN::Model::Cvterm->get_traits_from_component_categories($schema, \@allowed_composed_cvs, $composable_cvterm_delimiter, $composable_cvterm_format, $categories);
4471 my $existing_traits = $traits->{existing_traits};
4472 my $new_traits = $traits->{new_traits};
4473 # print STDERR Dumper $new_traits;
4474 # print STDERR Dumper $existing_traits;
4475 my %new_trait_names;
4476 foreach (@$new_traits) {
4477 my $components = $_->[0];
4478 $new_trait_names{$_->[1]} = join ',', @$components;
4481 my $onto = CXGN::Onto->new( { schema => $schema } );
4482 my $new_terms = $onto->store_composed_term(\%new_trait_names);
4484 my %composed_trait_map;
4485 while (my($trait_name, $trait_id) = each %trait_id_map) {
4486 my $components = [$trait_id, $stat_cvterm_id];
4487 my $composed_cvterm_id = SGN::Model::Cvterm->get_trait_from_exact_components($schema, $components);
4488 my $composed_trait_name = SGN::Model::Cvterm::get_trait_from_cvterm_id($schema, $composed_cvterm_id, 'extended');
4489 $composed_trait_map{$trait_name} = $composed_trait_name;
4491 my @composed_trait_names = values %composed_trait_map;
4493 my $time = DateTime->now();
4494 my $timestamp = $time->ymd()."_".$time->hms();
4496 my %derivative_results;
4497 no warnings 'uninitialized';
4498 foreach my $s (@sorted_plot_names) {
4499 foreach my $t (@sorted_trait_names) {
4500 my $trait = $composed_trait_map{$t};
4501 my @derivs;
4502 my $val = $phenotype_data{$s}->{$t};
4503 my $row = $rev_row{$s};
4504 my $col = $rev_col{$s};
4505 my @values = (
4506 $phenotype_data{$row_col_hash{$row-1}->{$col}}->{$t},
4507 $phenotype_data{$row_col_hash{$row+1}->{$col}}->{$t},
4508 $phenotype_data{$row_col_hash{$row}->{$col-1}}->{$t},
4509 $phenotype_data{$row_col_hash{$row}->{$col+1}}->{$t},
4511 $phenotype_data{$row_col_hash{$row-1}->{$col-1}}->{$t},
4512 $phenotype_data{$row_col_hash{$row+1}->{$col-1}}->{$t},
4513 $phenotype_data{$row_col_hash{$row-1}->{$col+1}}->{$t},
4514 $phenotype_data{$row_col_hash{$row+1}->{$col+1}}->{$t},
4516 $phenotype_data{$row_col_hash{$row-2}->{$col}}->{$t},
4517 $phenotype_data{$row_col_hash{$row+2}->{$col}}->{$t},
4518 $phenotype_data{$row_col_hash{$row}->{$col-2}}->{$t},
4519 $phenotype_data{$row_col_hash{$row}->{$col+2}}->{$t},
4521 $phenotype_data{$row_col_hash{$row-2}->{$col-2}}->{$t},
4522 $phenotype_data{$row_col_hash{$row+2}->{$col-2}}->{$t},
4523 $phenotype_data{$row_col_hash{$row-2}->{$col+2}}->{$t},
4524 $phenotype_data{$row_col_hash{$row+2}->{$col+2}}->{$t},
4526 $phenotype_data{$row_col_hash{$row-2}->{$col-1}}->{$t},
4527 $phenotype_data{$row_col_hash{$row+2}->{$col-1}}->{$t},
4528 $phenotype_data{$row_col_hash{$row-2}->{$col+1}}->{$t},
4529 $phenotype_data{$row_col_hash{$row+2}->{$col+1}}->{$t},
4531 $phenotype_data{$row_col_hash{$row-1}->{$col-2}}->{$t},
4532 $phenotype_data{$row_col_hash{$row+1}->{$col-2}}->{$t},
4533 $phenotype_data{$row_col_hash{$row-1}->{$col+2}}->{$t},
4534 $phenotype_data{$row_col_hash{$row+1}->{$col+2}}->{$t},
4536 $phenotype_data{$row_col_hash{$row-3}->{$col}}->{$t},
4537 $phenotype_data{$row_col_hash{$row+3}->{$col}}->{$t},
4538 $phenotype_data{$row_col_hash{$row}->{$col-3}}->{$t},
4539 $phenotype_data{$row_col_hash{$row}->{$col+3}}->{$t},
4541 $phenotype_data{$row_col_hash{$row-3}->{$col-3}}->{$t},
4542 $phenotype_data{$row_col_hash{$row+3}->{$col-3}}->{$t},
4543 $phenotype_data{$row_col_hash{$row-3}->{$col+3}}->{$t},
4544 $phenotype_data{$row_col_hash{$row+3}->{$col+3}}->{$t},
4546 $phenotype_data{$row_col_hash{$row-3}->{$col-1}}->{$t},
4547 $phenotype_data{$row_col_hash{$row+3}->{$col-1}}->{$t},
4548 $phenotype_data{$row_col_hash{$row-3}->{$col+1}}->{$t},
4549 $phenotype_data{$row_col_hash{$row+3}->{$col+1}}->{$t},
4551 $phenotype_data{$row_col_hash{$row-3}->{$col-2}}->{$t},
4552 $phenotype_data{$row_col_hash{$row+3}->{$col-2}}->{$t},
4553 $phenotype_data{$row_col_hash{$row-3}->{$col+2}}->{$t},
4554 $phenotype_data{$row_col_hash{$row+3}->{$col+2}}->{$t},
4556 $phenotype_data{$row_col_hash{$row-1}->{$col-3}}->{$t},
4557 $phenotype_data{$row_col_hash{$row+1}->{$col-3}}->{$t},
4558 $phenotype_data{$row_col_hash{$row-1}->{$col+3}}->{$t},
4559 $phenotype_data{$row_col_hash{$row+1}->{$col+3}}->{$t},
4561 $phenotype_data{$row_col_hash{$row-2}->{$col-3}}->{$t},
4562 $phenotype_data{$row_col_hash{$row+2}->{$col-3}}->{$t},
4563 $phenotype_data{$row_col_hash{$row-2}->{$col+3}}->{$t},
4564 $phenotype_data{$row_col_hash{$row+2}->{$col+3}}->{$t}
4567 foreach (@values) {
4568 if (defined($_)) {
4569 push @derivs, ($val - $_);
4570 push @derivs, ( (($val + $_)/8) - $_);
4571 push @derivs, ( (($val + $_)/4) - $_);
4572 push @derivs, ( (($val + $_)*3/8) - $_);
4573 push @derivs, ( (($val + $_)/2) - $_);
4574 push @derivs, ( (($val + $_)*5/8) - $_);
4575 push @derivs, ( (($val + $_)*3/4) - $_);
4576 push @derivs, ( (($val + $_)*7/8) - $_);
4579 # print STDERR Dumper \@derivs;
4580 if (scalar(@derivs) > 0) {
4581 my $d = sum(@derivs)/scalar(@derivs);
4582 $derivative_results{$s}->{$trait} = [$d, $timestamp, $user_name, '', ''];
4586 # print STDERR Dumper \%derivative_results;
4588 if (scalar(keys %derivative_results) != scalar(@sorted_plot_names)) {
4589 $c->stash->{rest} = { error => "Not all plots have rows and columns defined! Please make sure row and columns are saved for this field trial!"};
4590 return;
4593 my $dir = $c->tempfiles_subdir('/delete_nd_experiment_ids');
4594 my $temp_file_nd_experiment_id = $c->config->{basepath}."/".$c->tempfile( TEMPLATE => 'delete_nd_experiment_ids/fileXXXX');
4596 my %phenotype_metadata = (
4597 'archived_file' => 'none',
4598 'archived_file_type' => 'numerical_derivative_row_and_column_computation',
4599 'operator' => $user_name,
4600 'date' => $timestamp
4603 my $store_phenotypes = CXGN::Phenotypes::StorePhenotypes->new(
4604 basepath=>$c->config->{basepath},
4605 dbhost=>$c->config->{dbhost},
4606 dbname=>$c->config->{dbname},
4607 dbuser=>$c->config->{dbuser},
4608 dbpass=>$c->config->{dbpass},
4609 temp_file_nd_experiment_id=>$temp_file_nd_experiment_id,
4610 bcs_schema=>$schema,
4611 metadata_schema=>$metadata_schema,
4612 phenome_schema=>$phenome_schema,
4613 user_id=>$user_id,
4614 stock_list=>\@sorted_plot_names,
4615 trait_list=>\@composed_trait_names,
4616 values_hash=>\%derivative_results,
4617 has_timestamps=>0,
4618 overwrite_values=>1,
4619 ignore_new_values=>0,
4620 metadata_hash=>\%phenotype_metadata,
4621 composable_validation_check_name=>$c->config->{composable_validation_check_name}
4623 my ($verified_warning, $verified_error) = $store_phenotypes->verify();
4624 my ($stored_phenotype_error, $stored_Phenotype_success) = $store_phenotypes->store();
4626 my $bs = CXGN::BreederSearch->new( { dbh=>$c->dbc->dbh, dbname=>$c->config->{dbname}, } );
4627 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'fullview', 'concurrent', $c->config->{basepath});
4629 $c->stash->{rest} = {success => 1};
4634 # TRIAL ENTRY NUMBERS
4638 # Get an array of entry numbers for the specified trial
4639 # path param: trial id
4640 # return: an array of objects, with the following keys:
4641 # stock_id = id of the stock
4642 # stock_name = uniquename of the stock
4643 # entry_number = entry number for the stock in this trial
4645 sub get_entry_numbers : Chained('trial') PathPart('entry_numbers') Args(0) {
4646 my $self = shift;
4647 my $c = shift;
4648 my $schema = $c->dbic_schema("Bio::Chado::Schema");
4649 my $trial = $c->stash->{trial};
4651 # Get Entry Number map (stock_id -> entry number)
4652 my $entry_number_map = $trial->get_entry_numbers();
4653 my @entry_numbers;
4654 if ( $entry_number_map ) {
4656 # Parse each stock - get its name
4657 foreach my $stock_id (keys %$entry_number_map) {
4658 my $row = $schema->resultset("Stock::Stock")->find({ stock_id => int($stock_id) });
4659 my $stock_name = $row ? $row->uniquename() : 'STOCK NO LONGER EXISTS!';
4660 my $entry_number = $entry_number_map->{$stock_id};
4661 push(@entry_numbers, { stock_id => int($stock_id), stock_name => $stock_name, entry_number => $entry_number });
4666 # Return the array of entry number info
4667 $c->stash->{rest} = { entry_numbers => \@entry_numbers };
4671 # Create an entry number template for the specified trials
4672 # query param: 'trial_ids' = comma separated list of trial ids
4673 # return: 'file' = path to tempfile of excel template
4675 sub create_entry_number_template : Path('/ajax/breeders/trial_entry_numbers/create') Args(0) {
4676 my $self = shift;
4677 my $c = shift;
4678 my @trial_ids = split(',', $c->req->param('trial_ids'));
4679 my $schema = $c->dbic_schema("Bio::Chado::Schema");
4681 my $dir = $c->tempfiles_subdir('download');
4682 my $temp_file_name = "entry_numbers_XXXX";
4683 my $rel_file = $c->tempfile( TEMPLATE => "download/$temp_file_name");
4684 $rel_file = $rel_file . ".xlsx";
4685 my $tempfile = $c->config->{basepath}."/".$rel_file;
4687 my $download = CXGN::Trial::Download->new({
4688 bcs_schema => $schema,
4689 trial_list => \@trial_ids,
4690 filename => $tempfile,
4691 format => 'TrialEntryNumbers'
4693 my $error = $download->download();
4695 $c->stash->{rest} = { file => $tempfile };
4699 # Download an entry number template
4700 # query param: 'file' = path of entry number template tempfile to download
4701 # return: contents of excel file
4703 sub download_entry_number_template : Path('/ajax/breeders/trial_entry_numbers/download') Args(0) {
4704 my $self = shift;
4705 my $c = shift;
4706 my $tempfile = $c->req->param('file');
4708 $c->res->content_type('application/vnd.ms-excel');
4709 $c->res->header('Content-Disposition', qq[attachment; filename="entry_number_template.xls"]);
4710 my $output = read_file($tempfile);
4711 $c->res->body($output);
4715 # Upload an entry number template
4716 # upload params:
4717 # upload_entry_numbers_file: Excel file to validate and parse
4718 # ignore_warnings: true to add processed data if warnings exist
4719 # return: validation errors and warnings or success = 1 if entry numbers sucessfully stored
4720 # filename: original upload file name
4721 # error: array of error messages
4722 # warning: array of warning messages
4723 # missing_accessions: array of stock names not found in the database
4724 # missing_trials: array of trial names not found in database
4725 # success: set to `1` if file successfully validated and stored
4727 sub upload_entry_number_template : Path('/ajax/breeders/trial_entry_numbers/upload') : ActionClass('REST') { }
4728 sub upload_entry_number_template_POST : Args(0) {
4729 my $self = shift;
4730 my $c = shift;
4731 my $upload = $c->req->upload('upload_entry_numbers_file');
4732 my $ignore_warnings = $c->req->param('ignore_warnings') eq 'true';
4733 my $schema = $c->dbic_schema("Bio::Chado::Schema");
4734 my (@errors, %response);
4736 my $subdirectory = "trial_entry_numbers";
4737 my $upload_original_name = $upload->filename();
4738 my $upload_tempfile = $upload->tempname;
4739 my $time = DateTime->now();
4740 my $timestamp = $time->ymd()."_".$time->hms();
4742 ## Make sure user is logged in
4743 if ( !$c->user() ) {
4744 push(@errors, "You need to be logged in to upload entry numbers.");
4745 $c->stash->{rest} = { filename => $upload_original_name, error => \@errors };
4746 return;
4749 my $user_id = $c->user()->get_object()->get_sp_person_id();
4750 my $user_role = $c->user->get_object->get_user_type();
4752 ## Store uploaded temporary file in archive
4753 my $uploader = CXGN::UploadFile->new({
4754 tempfile => $upload_tempfile,
4755 subdirectory => $subdirectory,
4756 archive_path => $c->config->{archive_path},
4757 archive_filename => $upload_original_name,
4758 timestamp => $timestamp,
4759 user_id => $user_id,
4760 user_role => $user_role
4762 my $archived_filename_with_path = $uploader->archive();
4763 if ( !$archived_filename_with_path ) {
4764 push(@errors, "Could not save file $upload_original_name in archive");
4765 $c->stash->{rest} = { filename => $upload_original_name, error => \@errors };
4766 return;
4768 unlink $upload_tempfile;
4770 ## Parse the uploaded file
4771 my $parser = CXGN::Trial::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path);
4772 $parser->load_plugin('TrialEntryNumbers');
4773 my $parsed_data = $parser->parse();
4774 my $parse_errors = $parser->get_parse_errors();
4775 my $parse_warnings = $parser->get_parse_warnings();
4777 print STDERR "IGNORE WARNINGS: $ignore_warnings\n";
4779 ## Return with warnings and errors
4780 if ( $parse_errors || (!$ignore_warnings && $parse_warnings) || !$parsed_data ) {
4781 if ( !$parse_errors && !$parse_warnings ) {
4782 push(@errors, "Data could not be parsed");
4783 $c->stash->{rest} = { filename => $upload_original_name, error => \@errors };
4784 return;
4786 $c->stash->{rest} = {
4787 filename => $upload_original_name,
4788 error => $parse_errors->{'error_messages'},
4789 warning => $parse_warnings->{'warning_messages'},
4790 missing_accessions => $parse_errors->{'missing_accessions'},
4791 missing_trials => $parse_errors->{'missing_trials'}
4793 return;
4796 ## Process the parsed data
4797 foreach my $trial_id (keys %$parsed_data) {
4798 my $trial = CXGN::Trial->new({ bcs_schema => $schema, trial_id => $trial_id });
4799 $trial->set_entry_numbers($parsed_data->{$trial_id});
4802 $c->stash->{rest} = {
4803 success => 1,
4804 filename => $upload_original_name,
4805 warning => $parse_warnings->{'warning_messages'}
4807 return;
4811 sub update_trial_status : Chained('trial') PathPart('update_trial_status') : ActionClass('REST'){ }
4813 sub update_trial_status_POST : Args(0) {
4814 my $self = shift;
4815 my $c = shift;
4816 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
4817 my $trial_id = $c->stash->{trial_id};
4818 my $trial_status = $c->req->param("trial_status");
4819 my $user_name = $c->req->param("user_name");
4820 my $activity_date = $c->req->param("activity_date");
4822 if (!$c->user()) {
4823 $c->stash->{rest} = {error_string => "You must be logged in to update trial status." };
4824 return;
4826 my $user_id = $c->user()->get_object()->get_sp_person_id();
4828 my $trial_status_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'trial_status_json', 'project_property')->cvterm_id();
4829 my $prop = $schema->resultset("Project::Projectprop")->find({project_id => $trial_id, type_id => $trial_status_type_id});
4830 my $prop_id;
4831 my %all_activities_hash;
4832 if ($prop) {
4833 $prop_id = $prop->projectprop_id();
4834 my $status_json = $prop->value();
4835 my $status_hash_ref = decode_json $status_json;
4836 my $all_activities = $status_hash_ref->{'trial_activities'};
4837 %all_activities_hash = %{$all_activities};
4840 $all_activities_hash{$trial_status}{'user_id'} = $user_id;
4841 $all_activities_hash{$trial_status}{'activity_date'} = $activity_date;
4843 my $trial_status_obj = CXGN::TrialStatus->new({ bcs_schema => $schema });
4844 $trial_status_obj->trial_activities(\%all_activities_hash);
4845 $trial_status_obj->parent_id($trial_id);
4846 $trial_status_obj->prop_id($prop_id);
4847 my $project_prop_id = $trial_status_obj->store();
4849 $c->stash->{rest} = {success => 1 };
4850 return;
4855 sub get_all_trial_activities :Chained('trial') PathPart('all_trial_activities') Args(0){
4856 my $self = shift;
4857 my $c = shift;
4858 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
4859 my $people_schema = $c->dbic_schema("CXGN::People::Schema");
4860 my $trial_id = $c->stash->{trial_id};
4861 my $activities = $c->config->{'trial_activities'};
4862 my @activity_list = split ',', $activities;
4864 my $trial_status_obj = CXGN::TrialStatus->new({ bcs_schema => $schema, people_schema => $people_schema, parent_id => $trial_id, activity_list => \@activity_list });
4865 my $activity_info = $trial_status_obj->get_trial_activities();
4867 $c->stash->{rest} = { data => $activity_info };
4870 sub update_trial_design_type : Chained('trial') PathPart('update_trial_design_type') : ActionClass('REST'){ }
4872 sub update_trial_design_type_POST : Args(0) {
4873 my $self = shift;
4874 my $c = shift;
4875 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
4876 my $trial_design_type = $c->req->param("trial_design_type");
4878 if (!$c->user()) {
4879 $c->stash->{rest} = {error_string => "You must be logged in to update trial status." };
4880 return;
4882 my $user_id = $c->user()->get_object()->get_sp_person_id();
4883 my $curator = $c->user()->check_roles('curator') if $user_id;
4885 if (!$curator == 1) {
4886 $c->stash->{rest} = {error_string => "You must be curator to change experimental design type." };
4887 return;
4890 my $trial = $c->stash->{trial};
4892 $trial->set_design_type($trial_design_type);
4894 $c->stash->{rest} = {success => 1 };
4896 return;
4901 sub get_all_soil_data :Chained('trial') PathPart('all_soil_data') Args(0){
4902 my $self = shift;
4903 my $c = shift;
4904 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
4905 my $people_schema = $c->dbic_schema("CXGN::People::Schema");
4906 my $trial_id = $c->stash->{trial_id};
4908 my $soil_data_obj = CXGN::BreedersToolbox::SoilData->new({ bcs_schema => $schema, parent_id => $trial_id });
4909 my $soil_data = $soil_data_obj->get_all_soil_data();
4910 my @soil_data_list = @$soil_data;
4911 my @formatted_soil_data;
4912 foreach my $info_ref (@soil_data_list) {
4913 my @all_soil_data = ();
4914 my @info = @$info_ref;
4915 my $trial_id = pop @info;
4916 my $soil_data_details = pop @info;
4917 my $order_ref = pop @info;
4918 my @data_type_order = @$order_ref;
4919 foreach my $type(@data_type_order) {
4920 my $soil_data = $soil_data_details->{$type};
4921 my $soil_data_string = $type.":"." ".$soil_data;
4922 push @all_soil_data, $soil_data_string;
4924 my $soil_data_details_string = join("<br>", @all_soil_data);
4925 push @info, ($soil_data_details_string, "<a href='/breeders/trial/$trial_id/download/soil_data?format=soil_data_xls&dataLevel=soil_data&prop_id=$info[0]'>Download</a>");
4926 push @formatted_soil_data, {
4927 trial_id => $trial_id,
4928 prop_id => $info[0],
4929 description => $info[1],
4930 date => $info[2],
4931 gps => $info[3],
4932 type_of_sampling => $info[4],
4933 soil_data => $info[5],
4934 download_link => $info[6]
4938 $c->stash->{rest} = { data => \@formatted_soil_data };
4942 sub delete_soil_data : Chained('trial') PathPart('delete_soil_data') : ActionClass('REST'){ }
4944 sub delete_soil_data_POST : Args(0) {
4945 my $self = shift;
4946 my $c = shift;
4947 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
4948 my $prop_id = $c->req->param("prop_id");
4949 my $trial_id = $c->stash->{trial_id};
4950 my $session_id = $c->req->param("sgn_session_id");
4951 my $user_id;
4952 my $user_name;
4953 my $user_role;
4955 if ($session_id){
4956 my $dbh = $c->dbc->dbh;
4957 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
4958 if (!$user_info[0]){
4959 $c->stash->{rest} = {error=>'You must be logged in to delete soil data!'};
4960 $c->detach();
4962 $user_id = $user_info[0];
4963 $user_role = $user_info[1];
4964 my $p = CXGN::People::Person->new($dbh, $user_id);
4965 $user_name = $p->get_username;
4966 } else{
4967 if (!$c->user){
4968 $c->stash->{rest} = {error=>'You must be logged in to delete soil data!'};
4969 $c->detach();
4971 $user_id = $c->user()->get_object()->get_sp_person_id();
4972 $user_name = $c->user()->get_object()->get_username();
4973 $user_role = $c->user->get_object->get_user_type();
4976 if ($user_role ne 'curator') {
4977 $c->stash->{rest} = {error=>'Only a curator can delete soil data'};
4978 $c->detach();
4981 my $soil_data_obj = CXGN::BreedersToolbox::SoilData->new({ bcs_schema => $schema, parent_id => $trial_id, prop_id => $prop_id });
4982 my $error = $soil_data_obj->delete_soil_data();
4984 print STDERR "ERROR = $error\n";
4986 if ($error) {
4987 $c->stash->{rest} = { error => "An error occurred attempting to delete soil data. ($@)"};
4988 return;
4991 $c->stash->{rest} = { success => 1 };
4996 sub delete_all_genotyping_plates_in_project : Chained('trial') PathPart('delete_all_genotyping_plates_in_project') Args(0) {
4997 my $self = shift;
4998 my $c = shift;
4999 my $schema = $c->dbic_schema("Bio::Chado::Schema");
5000 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
5001 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
5003 my $genotyping_project_id = $c->stash->{trial_id};
5005 if (!$c->user()){
5006 $c->stash->{rest} = { error => "You must be logged in to delete genotyping plates" };
5007 $c->detach();
5009 if (!$c->user()->check_roles("curator")) {
5010 $c->stash->{rest} = { error => "You do not have the correct role to delete genotyping plates. Please contact us." };
5011 $c->detach();
5014 my $plate_info = CXGN::Genotype::GenotypingProject->new({
5015 bcs_schema => $schema,
5016 project_id => $genotyping_project_id
5018 my ($data, $total_count) = $plate_info->get_plate_info();
5019 my @genotyping_plate_ids;
5020 foreach my $plate(@$data){
5021 my $plate_id = $plate->{trial_id};
5022 push @genotyping_plate_ids, $plate_id;
5025 my $number_of_plates = @genotyping_plate_ids;
5026 my $error;
5027 if ($number_of_plates > 0){
5028 foreach my $plate_id (@genotyping_plate_ids) {
5029 my $trial = CXGN::Trial->new({
5030 bcs_schema => $schema,
5031 metadata_schema => $metadata_schema,
5032 phenome_schema => $phenome_schema,
5033 trial_id => $plate_id
5035 $error = $trial->delete_metadata();
5036 $error .= $trial->delete_field_layout();
5037 $error .= $trial->delete_project_entry();
5042 my $dbh = $c->dbc->dbh();
5043 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
5044 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath});
5046 if ($error) {
5047 $c->stash->{rest} = { error => $error };
5048 return;
5051 $c->stash->{rest} = { success => 1 };