4 SGN::Controller::AJAX::Cross - a REST controller class to provide the
5 functions for adding crosses
9 Add a new cross or upload a file containing crosses to add
13 Jeremy Edwards <jde22@cornell.edu>
14 Lukas Mueller <lam87@cornell.edu>
15 Titima Tantikanjana <tt15@cornell.edu>
19 package SGN
::Controller
::AJAX
::Cross
;
24 use Time
::HiRes
qw(time);
25 use POSIX
qw(strftime);
27 use File
::Basename qw
| basename dirname
|;
30 use File
::Spec
::Functions
;
32 use List
::MoreUtils qw
/any /;
33 use List
::MoreUtils
'none';
34 use Bio
::GeneticRelationships
::Pedigree
;
35 use Bio
::GeneticRelationships
::Individual
;
37 use CXGN
::Pedigree
::AddCrossingtrial
;
38 use CXGN
::Pedigree
::AddCrosses
;
39 use CXGN
::Pedigree
::AddProgeny
;
40 use CXGN
::Pedigree
::AddProgeniesExistingAccessions
;
41 use CXGN
::Pedigree
::AddCrossInfo
;
42 use CXGN
::Pedigree
::AddFamilyNames
;
43 use CXGN
::Pedigree
::AddPopulations
;
44 use CXGN
::Pedigree
::AddCrossTransaction
;
45 use CXGN
::Pedigree
::ParseUpload
;
46 use CXGN
::Trial
::Folder
;
47 use CXGN
::Trial
::TrialLayout
;
48 use CXGN
::Stock
::StockLookup
;
50 use File
::Path
qw(make_path);
51 use File
::Spec
::Functions qw
/ catfile catdir/;
54 use Tie
::UrlEncoder
; our(%urlencode);
57 use URI
::Encode
qw(uri_encode uri_decode);
58 use Sort
::Key
::Natural
qw(natsort);
61 BEGIN { extends
'Catalyst::Controller::REST' }
64 default => 'application/json',
66 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
69 sub upload_cross_file
: Path
('/ajax/cross/upload_crosses_file') : ActionClass
('REST') { }
71 sub upload_cross_file_POST
: Args
(0) {
73 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
74 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
75 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
76 my $dbh = $c->dbc->dbh;
77 my $manage_page_crossing_experiment_id = $c->req->param('upload_crosses_crossing_experiment_id');
78 my $experiment_page_crossing_experiment_id = $c->req->param('experiment_id');
79 my $crossing_trial_id;
80 if ($manage_page_crossing_experiment_id) {
81 $crossing_trial_id = $manage_page_crossing_experiment_id;
82 } elsif ($experiment_page_crossing_experiment_id) {
83 $crossing_trial_id = $experiment_page_crossing_experiment_id;
85 my $crosses_simple_upload = $c->req->upload('xls_crosses_simple_file');
86 my $crosses_plots_upload = $c->req->upload('xls_crosses_plots_file');
87 my $crosses_plants_upload = $c->req->upload('xls_crosses_plants_file');
88 my $crosses_simplified_parents_upload = $c->req->upload('xls_crosses_simplified_parents_file');
92 if ($crosses_plots_upload) {
93 $upload = $crosses_plots_upload;
94 $upload_type = 'CrossesExcelFormat';
96 if ($crosses_plants_upload) {
97 $upload = $crosses_plants_upload;
98 $upload_type = 'CrossesExcelFormat';
101 if ($crosses_simple_upload) {
102 $upload = $crosses_simple_upload;
103 $upload_type = 'CrossesSimpleExcel';
106 if ($crosses_simplified_parents_upload) {
107 $upload = $crosses_simplified_parents_upload;
108 $upload_type = 'CrossesSimplifiedParentInfoExcel';
113 my $upload_original_name = $upload->filename();
114 my $upload_tempfile = $upload->tempname;
115 my $subdirectory = "cross_upload";
116 my $archived_filename_with_path;
122 my $time = DateTime
->now();
123 my $timestamp = $time->ymd()."_".$time->hms();
128 my $session_id = $c->req->param("sgn_session_id");
131 my $dbh = $c->dbc->dbh;
132 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
134 $c->stash->{rest
} = {error
=>'You must be logged in to upload crosses!'};
137 $user_id = $user_info[0];
138 $user_role = $user_info[1];
139 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
140 $user_name = $p->get_username;
143 $c->stash->{rest
} = {error
=>'You must be logged in to upload crosses!'};
146 $user_id = $c->user()->get_object()->get_sp_person_id();
147 $user_name = $c->user()->get_object()->get_username();
148 $user_role = $c->user->get_object->get_user_type();
151 if (($user_role ne 'curator') && ($user_role ne 'submitter')) {
152 $c->stash->{rest
} = {error
=>'Only a submitter or a curator can upload crosses'};
156 my $uploader = CXGN
::UploadFile
->new({
157 tempfile
=> $upload_tempfile,
158 subdirectory
=> $subdirectory,
159 archive_path
=> $c->config->{archive_path
},
160 archive_filename
=> $upload_original_name,
161 timestamp
=> $timestamp,
163 user_role
=> $user_role
166 ## Store uploaded temporary file in arhive
167 $archived_filename_with_path = $uploader->archive();
168 $md5 = $uploader->get_md5($archived_filename_with_path);
169 if (!$archived_filename_with_path) {
170 $c->stash->{rest
} = {error
=> "Could not save file $upload_original_name in archive",};
173 unlink $upload_tempfile;
175 my $cross_additional_info_string = $c->config->{cross_additional_info
};
176 my @additional_info = split ',', $cross_additional_info_string;
177 my $cross_additional_info = \
@additional_info;
179 #parse uploaded file with appropriate plugin
180 $parser = CXGN
::Pedigree
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $archived_filename_with_path, cross_additional_info
=> $cross_additional_info);
181 $parser->load_plugin($upload_type);
182 $parsed_data = $parser->parse();
183 #print STDERR "Dumper of parsed data:\t" . Dumper($parsed_data) . "\n";
186 my $return_error = '';
188 if (!$parser->has_parse_errors() ){
189 $c->stash->{rest
} = {error_string
=> "Could not get parsing errors"};
191 $parse_errors = $parser->get_parse_errors();
192 #print STDERR Dumper $parse_errors;
194 foreach my $error_string (@
{$parse_errors->{'error_messages'}}){
195 $return_error .= $error_string."<br>";
198 $c->stash->{rest
} = {error_string
=> $return_error, missing_accessions
=> $parse_errors->{'missing_accessions'}, missing_plots
=> $parse_errors->{'missing_plots'}, missing_accessions_or_crosses
=> $parse_errors->{'missing_accessions_or_crosses'}};
202 my $md_row = $metadata_schema->resultset("MdMetadata")->create({create_person_id
=> $user_id});
204 my $upload_file = CXGN
::UploadFile
->new();
205 my $md5 = $upload_file->get_md5($archived_filename_with_path);
206 my $md5checksum = $md5->hexdigest();
207 my $file_row = $metadata_schema->resultset("MdFiles")->create({
208 basename
=> basename
($archived_filename_with_path),
209 dirname
=> dirname
($archived_filename_with_path),
210 filetype
=> 'crosses',
211 md5checksum
=> $md5checksum,
212 metadata_id
=> $md_row->metadata_id(),
214 my $file_id = $file_row->file_id();
216 my $cross_add = CXGN
::Pedigree
::AddCrosses
->new({
217 chado_schema
=> $chado_schema,
218 phenome_schema
=> $phenome_schema,
219 metadata_schema
=> $metadata_schema,
221 crossing_trial_id
=> $crossing_trial_id,
222 crosses
=> $parsed_data->{crosses
},
227 #validate the crosses
228 if (!$cross_add->validate_crosses()){
229 $c->stash->{rest
} = {error_string
=> "Error validating crosses",};
234 if (!$cross_add->add_crosses()){
235 $c->stash->{rest
} = {error_string
=> "Error adding crosses",};
239 if ($parsed_data->{'additional_info'}) {
240 my %cross_additional_info = %{$parsed_data->{additional_info
}};
241 foreach my $cross_name (keys %cross_additional_info) {
242 my %info_hash = %{$cross_additional_info{$cross_name}};
243 foreach my $info_type (keys %info_hash) {
244 my $value = $info_hash{$info_type};
245 my $cross_add_info = CXGN
::Pedigree
::AddCrossInfo
->new({
246 chado_schema
=> $chado_schema,
247 cross_name
=> $cross_name,
250 data_type
=> 'cross_additional_info'
253 $cross_add_info->add_info();
255 if (!$cross_add_info->add_info()){
256 $c->stash->{rest
} = {error_string
=> "Error saving info",};
264 $c->stash->{rest
} = {success
=> "1",};
268 sub add_cross
: Local
: ActionClass
('REST') { }
270 sub add_cross_POST
:Args
(0) {
272 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
273 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
274 my $cross_name = $c->req->param('cross_name');
275 my $cross_type = $c->req->param('cross_type');
276 my $crossing_trial_id = $c->req->param('crossing_trial_id');
277 my $female_plot_id = $c->req->param('female_plot');
278 my $male_plot_id = $c->req->param('male_plot');
279 my $cross_combination = $c->req->param('cross_combination');
280 $cross_name =~ s/^\s+|\s+$//g; #trim whitespace from front and end.
282 print STDERR
"CROSS COMBINATION=".Dumper
($cross_combination)."\n";
285 print STDERR
"User not logged in... not adding a cross.\n";
286 $c->stash->{rest
} = {error
=> "You need to be logged in to add a cross." };
290 if (!any
{ $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) {
291 print STDERR
"User does not have sufficient privileges.\n";
292 $c->stash->{rest
} = {error
=> "you have insufficient privileges to add a cross." };
295 $user_id = $c->user()->get_object()->get_sp_person_id();
298 if ($cross_type eq "polycross") {
299 print STDERR
"Handling a polycross\n";
300 my @maternal_parents = split (',', $c->req->param('maternal_parents'));
301 print STDERR
"Maternal parents array:" . @maternal_parents . "\n Maternal parents with ref:" . \
@maternal_parents . "\n Maternal parents with dumper:". Dumper
(@maternal_parents) . "\n";
302 my $paternal = $cross_name . '_population';
303 my $population_add = CXGN
::Pedigree
::AddPopulations
->new({ schema
=> $chado_schema, phenome_schema
=> $phenome_schema, user_id
=> $user_id, name
=> $paternal, members
=> \
@maternal_parents} );
304 $population_add->add_population();
305 $cross_type = 'polycross';
306 print STDERR
"Scalar maternatal paretns:" . scalar @maternal_parents;
307 for (my $i = 0; $i < scalar @maternal_parents; $i++) {
308 my $maternal = $maternal_parents[$i];
309 my $polycross_name = $cross_name . '_' . $maternal;
310 print STDERR
"First polycross to add is $polycross_name with amternal $maternal and paternal $paternal\n";
311 my $success = $self->add_individual_cross($c, $chado_schema, $polycross_name, $cross_type, $crossing_trial_id, $female_plot_id, $male_plot_id, $maternal, $paternal);
315 print STDERR
"polycross addition $polycross_name worked successfully\n";
318 elsif ($cross_type eq "reciprocal") {
319 $cross_type = 'biparental';
320 my @maternal_parents = split (',', $c->req->param('maternal_parents'));
321 for (my $i = 0; $i < scalar @maternal_parents; $i++) {
322 my $maternal = $maternal_parents[$i];
323 for (my $j = 0; $j < scalar @maternal_parents; $j++) {
324 my $paternal = $maternal_parents[$j];
325 if ($maternal eq $paternal) {
328 my $reciprocal_cross_name = $cross_name . '_' . $maternal . 'x' . $paternal . '_reciprocalcross';
329 my $success = $self->add_individual_cross($c, $chado_schema, $reciprocal_cross_name, $cross_type, $crossing_trial_id, $female_plot_id, $male_plot_id, $maternal, $paternal);
336 elsif ($cross_type eq "multicross") {
337 $cross_type = 'biparental';
338 my @maternal_parents = split (',', $c->req->param('maternal_parents'));
339 my @paternal_parents = split (',', $c->req->param('paternal_parents'));
340 for (my $i = 0; $i < scalar @maternal_parents; $i++) {
341 my $maternal = $maternal_parents[$i];
342 my $paternal = $paternal_parents[$i];
343 my $multicross_name = $cross_name . '_' . $maternal . 'x' . $paternal . '_multicross';
344 my $success = $self->add_individual_cross($c, $chado_schema, $multicross_name, $cross_type, $crossing_trial_id, $female_plot_id, $male_plot_id, $maternal, $paternal);
351 my $maternal = $c->req->param('maternal');
352 my $paternal = $c->req->param('paternal');
353 my $success = $self->add_individual_cross($c, $chado_schema, $cross_name, $cross_type, $crossing_trial_id, $female_plot_id, $male_plot_id, $maternal, $paternal, $cross_combination);
358 $c->stash->{rest
} = {success
=> "1",};
361 sub get_cross_relationships
:Path
('/cross/ajax/relationships') :Args
(1) {
364 my $cross_id = shift;
366 my $schema = $c->dbic_schema("Bio::Chado::Schema");
368 my $cross = $schema->resultset("Stock::Stock")->find( { stock_id
=> $cross_id });
370 if ($cross && $cross->type()->name() ne "cross") {
371 $c->stash->{rest
} = { error
=> 'This entry is not of type cross and cannot be displayed using this page.' };
375 my $cross_obj = CXGN
::Cross
->new({schema
=>$schema, cross_stock_id
=>$cross_id});
376 my ($maternal_parent, $paternal_parent, $progeny) = $cross_obj->get_cross_relationships();
378 $c->stash->{rest
} = {
379 maternal_parent
=> $maternal_parent,
380 paternal_parent
=> $paternal_parent,
386 sub get_membership
:Path
('/ajax/cross/membership') :Args
(1) {
389 my $cross_id = shift;
391 my $schema = $c->dbic_schema("Bio::Chado::Schema");
393 my $cross = $schema->resultset("Stock::Stock")->find( { stock_id
=> $cross_id });
395 if ($cross && $cross->type()->name() ne "cross") {
396 $c->stash->{rest
} = { error
=> 'This entry is not of type cross and cannot be displayed using this page.' };
400 my $cross_obj = CXGN
::Cross
->new({schema
=>$schema, cross_stock_id
=>$cross_id});
401 my $result = $cross_obj->get_membership();
404 foreach my $r (@
$result){
405 my ($crossing_experiment_id, $crossing_experiment_name, $description, $family_id, $family_name) =@
$r;
406 push @membership_info, [qq{<a href
="/breeders/trial/$crossing_experiment_id">$crossing_experiment_name</a
>}, $description, qq{<a href
= "/family/$family_id/">$family_name</a
>}];
409 $c->stash->{rest
} = { data
=> \
@membership_info };
414 sub get_cross_parents
:Path
('/ajax/cross/accession_plot_plant_parents') Args
(1) {
417 my $cross_id = shift;
419 my $schema = $c->dbic_schema("Bio::Chado::Schema");
420 my $cross = $schema->resultset("Stock::Stock")->find( { stock_id
=> $cross_id });
422 if ($cross && $cross->type()->name() ne "cross") {
423 $c->stash->{rest
} = { error
=> 'This entry is not of type cross and cannot be displayed using this page.' };
427 my $cross_obj = CXGN
::Cross
->new({schema
=>$schema, cross_stock_id
=>$cross_id});
428 my $result = $cross_obj->cross_parents();
429 my @cross_parent_info;
431 foreach my $r (@
$result){
432 my ($female_accession_id, $female_accession_name, $female_plot_id, $female_plot_name, $female_plant_id, $female_plant_name, $male_accession_id, $male_accession_name, $male_plot_id, $male_plot_name, $male_plant_id, $male_plant_name, $cross_type, $cross_combination, $female_ploidy, $male_ploidy) = @
$r;
433 push @cross_parent_info, [$cross_combination, $cross_type,
434 qq{<a href
="/stock/$female_accession_id/view">$female_accession_name</a
>},
436 qq{<a href
="/stock/$male_accession_id/view">$male_accession_name</a
>},
438 qq{<a href
="/stock/$female_plot_id/view">$female_plot_name</a
>},
439 qq{<a href
="/stock/$male_plot_id/view">$male_plot_name</a
>},
440 qq{<a href
="/stock/$female_plant_id/view">$female_plant_name</a
>},
441 qq{<a href
="/stock/$male_plant_id/view">$male_plant_name</a
>}];
444 $c->stash->{rest
} = {data
=> \
@cross_parent_info}
449 sub get_cross_properties
:Path
('/ajax/cross/properties') Args
(1) {
452 my $cross_id = shift;
454 my $schema = $c->dbic_schema("Bio::Chado::Schema");
455 my $cross_info_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'crossing_metadata_json', 'stock_property')->cvterm_id();
456 my $cross_info = $schema->resultset("Stock::Stockprop")->find({stock_id
=> $cross_id, type_id
=> $cross_info_cvterm});
458 my $cross_json_string;
460 $cross_json_string = $cross_info->value();
463 my $cross_props_hash ={};
464 if($cross_json_string){
465 $cross_props_hash = decode_json
$cross_json_string;
468 my $cross_properties = $c->config->{cross_properties
};
469 my @column_order = split ',',$cross_properties;
472 foreach my $key (@column_order){
473 push @row, $cross_props_hash->{$key};
477 $c->stash->{rest
} = {data
=> \
@props};
482 sub get_cross_tissue_culture_summary
:Path
('/ajax/cross/tissue_culture_summary') Args
(1) {
485 my $cross_id = shift;
486 my $schema = $c->dbic_schema("Bio::Chado::Schema");
488 my $cross_samples_obj = CXGN
::Cross
->new({schema
=>$schema, cross_stock_id
=>$cross_id});
489 my $cross_sample_data = $cross_samples_obj->get_cross_tissue_culture_samples();
491 my $embryo_ids = $cross_sample_data->{'Embryo IDs'};
492 my $subculture_ids = $cross_sample_data->{'Subculture IDs'};
493 my $rooting_ids = $cross_sample_data->{'Rooting IDs'};
494 my $weaning1_ids = $cross_sample_data->{'Weaning1 IDs'};
495 my $weaning2_ids = $cross_sample_data->{'Weaning2 IDs'};
496 my $screenhouse_ids = $cross_sample_data->{'Screenhouse IDs'};
497 my $hardening_ids = $cross_sample_data->{'Hardening IDs'};
498 my $openfield_ids = $cross_sample_data->{'Openfield IDs'};
500 my @embryo_ids_array;
501 my @subculture_ids_array;
502 my @rooting_ids_array;
503 my @weaning1_ids_array;
504 my @weaning2_ids_array;
505 my @screenhouse_ids_array;
506 my @hardening_ids_array;
507 my @openfield_ids_array;
509 if (defined $embryo_ids) {
510 @embryo_ids_array = @
$embryo_ids;
513 if (defined $subculture_ids) {
514 @subculture_ids_array = @
$subculture_ids;
517 if (defined $rooting_ids) {
518 @rooting_ids_array = @
$rooting_ids;
521 if (defined $weaning1_ids) {
522 @weaning1_ids_array = @
$weaning1_ids;
525 if (defined $weaning2_ids) {
526 @weaning2_ids_array = @
$weaning2_ids;
529 if (defined $screenhouse_ids) {
530 @screenhouse_ids_array = @
$screenhouse_ids;
533 if (defined $hardening_ids) {
534 @hardening_ids_array = @
$hardening_ids;
537 if (defined $openfield_ids) {
538 @openfield_ids_array = @
$openfield_ids;
543 my $checkmark = qq{<img src
="/img/checkmark_green.jpg"/>};
544 my $x_mark = qq{<img src
="/img/x_mark_red.jpg"/>};
545 my @sorted_embryo_ids = natsort
@embryo_ids_array;
547 foreach my $embryo_id (@sorted_embryo_ids) {
550 push @each_row, $embryo_id;
553 if ($embryo_id ~~ @subculture_ids_array) {
554 push @each_row, $checkmark;
556 push @each_row, $x_mark;
559 if ($embryo_id ~~ @rooting_ids_array) {
560 push @each_row, $checkmark;
562 push @each_row, $x_mark;
565 if ($embryo_id ~~ @weaning1_ids_array) {
566 push @each_row, $checkmark;
568 push @each_row, $x_mark;
571 if ($embryo_id ~~ @weaning2_ids_array) {
572 push @each_row, $checkmark;
574 push @each_row, $x_mark;
577 if ($embryo_id ~~ @screenhouse_ids_array) {
578 push @each_row, $checkmark;
580 push @each_row, $x_mark;
583 if ($embryo_id ~~ @hardening_ids_array) {
584 push @each_row, $checkmark;
586 push @each_row, $x_mark;
589 if ($embryo_id ~~ @openfield_ids_array) {
590 push @each_row, $checkmark;
592 push @each_row, $x_mark;
595 push @all_rows, [@each_row];
598 # print STDERR "SORTED EMBRYO IDS =".Dumper(\@sorted_embryo_ids)."\n";
599 $c->stash->{rest
} = { data
=> \
@all_rows };
603 sub save_property_check
:Path
('/cross/property/check') Args
(1) {
606 my $cross_id = shift;
608 my $type = $c->req->param("type");
609 my $value = $c->req->param("value");
612 my $schema = $c->dbic_schema("Bio::Chado::Schema");
614 if ($type =~ m/Number/ || $type =~ m/Days/) { $type = 'number';}
615 if ($type =~ m/Date/) { $type = 'date';}
617 my %suggested_values = (
618 # cross_name => '.*',
619 # cross_type => { 'biparental'=>1, 'self'=>1, 'open'=>1, 'bulk'=>1, 'bulk_self'=>1, 'bulk_open'=>1, 'doubled_haploid'=>1 },
621 date
=> '\d{4}\\/\d{2}\\/\d{2}',
624 my %example_values = (
625 date
=> '2014/03/29',
627 # cross_type => 'biparental',
628 # cross_name => 'nextgen_cross',
631 if (ref($suggested_values{$type})) {
632 if (!exists($suggested_values{$type}->{$value})) { # don't make this case insensitive!
633 $c->stash->{rest
} = { message
=> 'The provided value is not in the suggested list of terms. This could affect downstream data processing.' };
638 if ($value !~ m/^$suggested_values{$type}$/) {
639 $c->stash->{rest
} = { error
=> 'The provided value is not in a valid format. Format example: "'.$example_values{$type}.'"' };
643 $c->stash->{rest
} = { success
=> 1 };
648 sub cross_property_save
:Path
('/cross/property/save') Args
(1) {
653 $c->stash->{rest
} = { error
=> "You must be logged in to add properties." };
656 if (!($c->user()->has_role('submitter') or $c->user()->has_role('curator'))) {
657 $c->stash->{rest
} = { error
=> "You do not have sufficient privileges to add properties." };
661 my $cross_id = $c->req->param("cross_id");
662 my $type = $c->req->param("type");
663 my $value = $c->req->param("value");
664 my $data_type = $c->req->param("data_type");
665 # print STDERR "DATA TYPE =".Dumper($data_type)."\n";
666 # print STDERR "TYPE =".Dumper($type)."\n";
667 # print STDERR "VALUE =".Dumper($value)."\n";
669 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
670 my $cross_name = $schema->resultset("Stock::Stock")->find({stock_id
=> $cross_id})->uniquename();
672 my $cross_add_info = CXGN
::Pedigree
::AddCrossInfo
->new({
673 chado_schema
=> $schema,
674 cross_name
=> $cross_name,
677 data_type
=> $data_type
679 $cross_add_info->add_info();
681 if (!$cross_add_info->add_info()){
682 $c->stash->{rest
} = {error_string
=> "Error saving info",};
686 $c->stash->{rest
} = { success
=> 1};
689 sub add_more_progeny
:Path
('/cross/progeny/add') Args
(1) {
692 my $cross_id = shift;
695 $c->stash->{rest
} = { error
=> "You must be logged in add progeny." };
698 if (!($c->user()->has_role('submitter') or $c->user()->has_role('curator'))) {
699 $c->stash->{rest
} = { error
=> "You do not have sufficient privileges to add progeny." };
703 my $basename = $c->req->param("basename");
704 my $start_number = $c->req->param("start_number");
705 my $progeny_count = $c->req->param("progeny_count");
706 my $cross_name = $c->req->param("cross_name");
708 my @progeny_names = ();
709 foreach my $n (1..$progeny_count) {
710 push @progeny_names, $basename. (sprintf "%03d", $n + $start_number -1);
713 #print STDERR Dumper(\@progeny_names);
715 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
716 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
717 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
718 my $dbh = $c->dbc->dbh;
720 my $owner_name = $c->user()->get_object()->get_username();
722 my $progeny_add = CXGN
::Pedigree
::AddProgeny
724 chado_schema
=> $chado_schema,
725 phenome_schema
=> $phenome_schema,
727 cross_name
=> $cross_name,
728 progeny_names
=> \
@progeny_names,
729 owner_name
=> $owner_name,
731 if (!$progeny_add->add_progeny()){
732 $c->stash->{rest
} = {error_string
=> "Error adding progeny. Please change the input parameters and try again.",};
733 #should delete crosses and other progeny if add progeny fails?
737 $c->stash->{rest
} = { success
=> 1};
742 #my $new_cross = CXGN::Cross->new({ schema=>schema });
743 #$new_cross->female_parent($fjfj);
744 #$new_cross->male_parent(kdkjf);
745 #$new_cross->location(kjlsdlkjdfskj);
749 #$new_cross->store();
751 sub add_individual_cross
{
754 my $chado_schema = shift;
755 my $cross_name = shift;
756 my $cross_type = shift;
757 my $crossing_trial_id = shift;
758 my $female_plot_id = shift;
760 my $male_plot_id = shift;
762 my $maternal = shift;
763 my $paternal = shift;
764 my $cross_combination = shift;
766 my $owner_name = $c->user()->get_object()->get_username();
767 my $user_id = $c->user()->get_object()->get_sp_person_id();
769 my $progeny_increment = 1;
770 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
771 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
772 my $dbh = $c->dbc->dbh;
773 my $prefix = $c->req->param('prefix');
774 my $suffix = $c->req->param('suffix');
775 my $progeny_number = $c->req->param('progeny_number');
776 my $visible_to_role = $c->req->param('visible_to_role');
778 if ($female_plot_id){
779 my $female_plot_rs = $chado_schema->resultset("Stock::Stock")->find({stock_id
=> $female_plot_id});
780 $female_plot = $female_plot_rs->name();
784 my $male_plot_rs = $chado_schema->resultset("Stock::Stock")->find({stock_id
=> $male_plot_id});
785 $male_plot = $male_plot_rs->name();
789 #check that progeny number is an integer less than maximum allowed
790 my $maximum_progeny_number = 999; #higher numbers break cross name convention
791 if ($progeny_number) {
792 if ((! $progeny_number =~ m/^\d+$/) or ($progeny_number > $maximum_progeny_number) or ($progeny_number < 1)) {
793 $c->stash->{rest
} = {error
=> "progeny number exceeds the maximum of $maximum_progeny_number or is invalid." };
798 #check that maternal name is not blank
799 if ($maternal eq "") {
800 $c->stash->{rest
} = {error
=> "Female parent name cannot be blank." };
804 #if required, check that paternal parent name is not blank;
805 if ($paternal eq "" && ($cross_type ne "open") && ($cross_type ne "bulk_open")) {
806 $c->stash->{rest
} = {error
=> "Male parent name cannot be blank." };
810 #check that parents exist in the database
811 if (! $chado_schema->resultset("Stock::Stock")->find({uniquename
=>$maternal,})){
812 $c->stash->{rest
} = {error
=> "Female parent does not exist." };
817 if (! $chado_schema->resultset("Stock::Stock")->find({uniquename
=>$paternal,})){
818 $c->stash->{rest
} = {error
=> "Male parent does not exist." };
823 #check that cross name does not already exist
824 if ($chado_schema->resultset("Stock::Stock")->find({uniquename
=>$cross_name})){
825 $c->stash->{rest
} = {error
=> "Cross Unique ID already exists." };
829 #check that progeny do not already exist
830 if ($chado_schema->resultset("Stock::Stock")->find({uniquename
=>$cross_name.$prefix.'001'.$suffix,})){
831 $c->stash->{rest
} = {error
=> "progeny already exist." };
835 #objects to store cross information
836 my $cross_to_add = Bio
::GeneticRelationships
::Pedigree
->new(name
=> $cross_name, cross_type
=> $cross_type, cross_combination
=> $cross_combination,);
837 my $female_individual = Bio
::GeneticRelationships
::Individual
->new(name
=> $maternal);
838 $cross_to_add->set_female_parent($female_individual);
841 my $male_individual = Bio
::GeneticRelationships
::Individual
->new(name
=> $paternal);
842 $cross_to_add->set_male_parent($male_individual);
846 my $female_plot_individual = Bio
::GeneticRelationships
::Individual
->new(name
=> $female_plot);
847 $cross_to_add->set_female_plot($female_plot_individual);
851 my $male_plot_individual = Bio
::GeneticRelationships
::Individual
->new(name
=> $male_plot);
852 $cross_to_add->set_male_plot($male_plot_individual);
855 $cross_to_add->set_cross_type($cross_type);
856 $cross_to_add->set_name($cross_name);
857 $cross_to_add->set_cross_combination($cross_combination);
860 #create array of pedigree objects to add, in this case just one pedigree
861 my @array_of_pedigree_objects = ($cross_to_add);
862 my $cross_add = CXGN
::Pedigree
::AddCrosses
864 chado_schema
=> $chado_schema,
865 phenome_schema
=> $phenome_schema,
867 crossing_trial_id
=> $crossing_trial_id,
868 crosses
=> \
@array_of_pedigree_objects,
873 $cross_add->add_crosses();
877 $c->stash->{rest
} = { error
=> "Error creating the cross: $@" };
882 #create progeny if specified
883 if ($progeny_number) {
884 #create array of progeny names to add for this cross
885 while ($progeny_increment < $progeny_number + 1) {
886 $progeny_increment = sprintf "%03d", $progeny_increment;
887 my $stock_name = $cross_name.$prefix.$progeny_increment.$suffix;
888 push @progeny_names, $stock_name;
889 $progeny_increment++;
892 #add array of progeny to the cross
893 my $progeny_add = CXGN
::Pedigree
::AddProgeny
895 chado_schema
=> $chado_schema,
896 phenome_schema
=> $phenome_schema,
898 cross_name
=> $cross_name,
899 progeny_names
=> \
@progeny_names,
900 owner_name
=> $owner_name,
902 $progeny_add->add_progeny();
907 $c->stash->{rest
} = { error
=> "An error occurred: $@"};
915 sub add_crossingtrial
: Path
('/ajax/cross/add_crossingtrial') : ActionClass
('REST') {}
917 sub add_crossingtrial_POST
:Args
(0){
919 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
920 my $dbh = $c->dbc->dbh;
921 my $crossingtrial_name = $c->req->param('crossingtrial_name');
922 my $breeding_program_id = $c->req->param('crossingtrial_program_id');
923 my $location = $c->req->param('crossingtrial_location');
924 my $year = $c->req->param('year');
925 my $project_description = $c->req->param('project_description');
928 print STDERR
"User not logged in... not adding a crossing experiment.\n";
929 $c->stash->{rest
} = {error
=> "You need to be logged in to add a crossing experiment."};
933 if (!any
{ $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles)){
934 print STDERR
"User does not have sufficient privileges.\n";
935 $c->stash->{rest
} = {error
=> "you have insufficient privileges to add a crossing experiment." };
939 my $user_id = $c->user()->get_object()->get_sp_person_id();
941 my $geolocation_lookup = CXGN
::Location
::LocationLookup
->new(schema
=>$schema);
942 $geolocation_lookup->set_location_name($location);
943 if(!$geolocation_lookup->get_geolocation()){
944 $c->stash->{rest
}={error
=> "Location not found"};
950 my $add_crossingtrial = CXGN
::Pedigree
::AddCrossingtrial
->new({
951 chado_schema
=> $schema,
953 breeding_program_id
=> $breeding_program_id,
955 project_description
=> $project_description,
956 crossingtrial_name
=> $crossingtrial_name,
957 nd_geolocation_id
=> $geolocation_lookup->get_geolocation()->nd_geolocation_id(),
960 my $store_return = $add_crossingtrial->save_crossingtrial();
961 if ($store_return->{error
}){
962 $error = $store_return->{error
};
967 $c->stash->{rest
} = {error
=> $@
};
972 $c->stash->{rest
} = {error
=> $error};
974 $c->stash->{rest
} = {success
=> 1};
978 sub upload_progenies
: Path
('/ajax/cross/upload_progenies') : ActionClass
('REST'){ }
980 sub upload_progenies_POST
: Args
(0) {
983 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
984 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
985 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
986 my $dbh = $c->dbc->dbh;
987 my $upload = $c->req->upload('progenies_new_upload_file');
988 my $upload_type = 'ProgeniesExcel';
991 my $upload_original_name = $upload->filename();
992 my $upload_tempfile = $upload->tempname;
993 my $subdirectory = "cross_upload";
994 my $archived_filename_with_path;
1000 my $time = DateTime
->now();
1001 my $timestamp = $time->ymd()."_".$time->hms();
1006 # my $upload_file_type = "crosses excel";#get from form when more options are added
1007 my $session_id = $c->req->param("sgn_session_id");
1010 my $dbh = $c->dbc->dbh;
1011 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
1012 if (!$user_info[0]){
1013 $c->stash->{rest
} = {error
=>'You must be logged in to upload progenies!'};
1016 $user_id = $user_info[0];
1017 $user_role = $user_info[1];
1018 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
1019 $user_name = $p->get_username;
1022 $c->stash->{rest
} = {error
=>'You must be logged in to upload progenies!'};
1025 $user_id = $c->user()->get_object()->get_sp_person_id();
1026 $user_name = $c->user()->get_object()->get_username();
1027 $user_role = $c->user->get_object->get_user_type();
1030 if (($user_role ne 'curator') && ($user_role ne 'submitter')) {
1031 $c->stash->{rest
} = {error
=>'Only a submitter or a curator can upload progenies'};
1035 my $uploader = CXGN
::UploadFile
->new({
1036 tempfile
=> $upload_tempfile,
1037 subdirectory
=> $subdirectory,
1038 archive_path
=> $c->config->{archive_path
},
1039 archive_filename
=> $upload_original_name,
1040 timestamp
=> $timestamp,
1041 user_id
=> $user_id,
1042 user_role
=> $user_role
1045 ## Store uploaded temporary file in arhive
1046 $archived_filename_with_path = $uploader->archive();
1047 $md5 = $uploader->get_md5($archived_filename_with_path);
1048 if (!$archived_filename_with_path) {
1049 $c->stash->{rest
} = {error
=> "Could not save file $upload_original_name in archive",};
1052 unlink $upload_tempfile;
1054 #parse uploaded file with appropriate plugin
1055 $parser = CXGN
::Pedigree
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $archived_filename_with_path);
1056 $parser->load_plugin($upload_type);
1057 $parsed_data = $parser->parse();
1058 #print STDERR "Dumper of parsed data:\t" . Dumper($parsed_data) . "\n";
1061 my $return_error = '';
1063 if (!$parser->has_parse_errors() ){
1064 $c->stash->{rest
} = {error_string
=> "Could not get parsing errors"};
1066 $parse_errors = $parser->get_parse_errors();
1067 #print STDERR Dumper $parse_errors;
1069 foreach my $error_string (@
{$parse_errors->{'error_messages'}}){
1070 $return_error .= $error_string."<br>";
1073 $c->stash->{rest
} = {error_string
=> $return_error};
1078 my %progeny_hash = %{$parsed_data};
1079 my @all_crosses = keys %progeny_hash;
1080 foreach my $cross_name_key (keys %progeny_hash){
1081 my $progenies_ref = $progeny_hash{$cross_name_key};
1082 my @progenies = @
{$progenies_ref};
1083 my $progeny_add = CXGN
::Pedigree
::AddProgeny
->new({
1084 chado_schema
=> $chado_schema,
1085 phenome_schema
=> $phenome_schema,
1087 cross_name
=> $cross_name_key,
1088 progeny_names
=> \
@progenies,
1089 owner_name
=> $user_name,
1091 if (!$progeny_add->add_progeny()){
1092 $c->stash->{rest
} = {error_string
=> "Error adding progeny",};
1097 my $md_row = $metadata_schema->resultset("MdMetadata")->create({create_person_id
=> $user_id});
1099 my $upload_file = CXGN
::UploadFile
->new();
1100 my $md5 = $upload_file->get_md5($archived_filename_with_path);
1101 my $md5checksum = $md5->hexdigest();
1102 my $file_row = $metadata_schema->resultset("MdFiles")->create({
1103 basename
=> basename
($archived_filename_with_path),
1104 dirname
=> dirname
($archived_filename_with_path),
1105 filetype
=> 'cross_progenies',
1106 md5checksum
=> $md5checksum,
1107 metadata_id
=> $md_row->metadata_id(),
1110 my $file_id = $file_row->file_id();
1111 # print STDERR "FILE ID =".Dumper($file_id)."\n";
1112 foreach my $cross_name (@all_crosses) {
1113 my $cross_experiment_type = CXGN
::Cross
->new({schema
=> $chado_schema, cross_name
=> $cross_name});
1114 my $experiment_id = $cross_experiment_type->get_nd_experiment_id_with_type_cross_experiment();
1115 # print STDERR "ND EXPERIMENT ID =".Dumper($experiment_id)."\n";
1116 my $nd_experiment_file = $phenome_schema->resultset("NdExperimentMdFiles")->create({
1117 nd_experiment_id
=> $experiment_id,
1118 file_id
=> $file_id,
1122 $c->stash->{rest
} = {success
=> "1",};
1126 sub validate_upload_existing_progenies
: Path
('/ajax/cross/validate_upload_existing_progenies') : ActionClass
('REST'){ }
1128 sub validate_upload_existing_progenies_POST
: Args
(0) {
1131 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
1132 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
1133 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
1134 my $dbh = $c->dbc->dbh;
1135 my $upload = $c->req->upload('progenies_exist_upload_file');
1136 my $upload_type = 'ValidateExistingProgeniesExcel';
1139 my $upload_original_name = $upload->filename();
1140 my $upload_tempfile = $upload->tempname;
1141 my $subdirectory = "cross_upload";
1142 my $archived_filename_with_path;
1148 my $time = DateTime
->now();
1149 my $timestamp = $time->ymd()."_".$time->hms();
1154 # my $upload_file_type = "crosses excel";#get from form when more options are added
1155 my $session_id = $c->req->param("sgn_session_id");
1157 my $dbh = $c->dbc->dbh;
1158 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
1159 if (!$user_info[0]){
1160 $c->stash->{rest
} = {error
=>'You must be logged in to upload progenies!'};
1163 $user_id = $user_info[0];
1164 $user_role = $user_info[1];
1165 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
1166 $user_name = $p->get_username;
1169 $c->stash->{rest
} = {error
=>'You must be logged in to upload progenies!'};
1172 $user_id = $c->user()->get_object()->get_sp_person_id();
1173 $user_name = $c->user()->get_object()->get_username();
1174 $user_role = $c->user->get_object->get_user_type();
1177 if (($user_role ne 'curator') && ($user_role ne 'submitter')) {
1178 $c->stash->{rest
} = {error
=>'Only a submitter or a curator can upload progenies'};
1182 my $uploader = CXGN
::UploadFile
->new({
1183 tempfile
=> $upload_tempfile,
1184 subdirectory
=> $subdirectory,
1185 archive_path
=> $c->config->{archive_path
},
1186 archive_filename
=> $upload_original_name,
1187 timestamp
=> $timestamp,
1188 user_id
=> $user_id,
1189 user_role
=> $user_role
1192 ## Store uploaded temporary file in arhive
1193 $archived_filename_with_path = $uploader->archive();
1194 $md5 = $uploader->get_md5($archived_filename_with_path);
1195 if (!$archived_filename_with_path) {
1196 $c->stash->{rest
} = {error
=> "Could not save file $upload_original_name in archive",};
1199 unlink $upload_tempfile;
1201 #parse uploaded file with appropriate plugin
1202 $parser = CXGN
::Pedigree
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $archived_filename_with_path);
1203 $parser->load_plugin($upload_type);
1204 $parsed_data = $parser->parse();
1205 #print STDERR "Dumper of parsed data:\t" . Dumper($parsed_data) . "\n";
1207 my $return_error = '';
1208 my $existing_pedigree = '';
1209 if (!$parser->has_parse_errors() ){
1210 $c->stash->{rest
} = {error_string
=> "Could not get parsing errors"};
1212 $parse_errors = $parser->get_parse_errors();
1213 #print STDERR Dumper $parse_errors;
1215 foreach my $error_string (@
{$parse_errors->{'error_messages'}}){
1216 $return_error .= $error_string."<br>";
1219 foreach my $each_pedigree (@
{$parse_errors->{'existing_pedigrees'}}){
1220 $existing_pedigree .= $each_pedigree."<br>";
1224 $c->stash->{rest
} = {error_string
=> $return_error, existing_pedigrees
=> $existing_pedigree, archived_file_name
=> $archived_filename_with_path, user_id
=> $user_id};
1228 sub store_upload_existing_progenies
: Path
('/ajax/cross/store_upload_existing_progenies') Args
(0) {
1231 my $archived_filename_with_path = $c->req->param('archived_file_name');
1232 my $user_id = $c->req->param('user_id');
1233 # print STDERR "ARCHIVED FILE NAME =".Dumper($archived_filename_with_path)."\n";
1234 # print STDERR "USER ID =".Dumper($user_id)."\n";
1235 my $overwrite_pedigrees = $c->req->param('overwrite_pedigrees') ne 'false' ?
$c->req->param('overwrite_pedigrees') : 0;
1236 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
1237 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
1238 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
1239 my $dbh = $c->dbc->dbh;
1241 my $upload_type = 'StoreExistingProgeniesExcel';
1244 my $parser = CXGN
::Pedigree
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $archived_filename_with_path);
1245 $parser->load_plugin($upload_type);
1246 my $parsed_data = $parser->parse();
1248 my %progeny_hash = %{$parsed_data};
1249 @all_crosses = keys %progeny_hash;
1250 foreach my $cross_name_key (keys %progeny_hash){
1251 my $progenies_ref = $progeny_hash{$cross_name_key};
1252 my @progenies = @
{$progenies_ref};
1253 my $adding_progenies = CXGN
::Pedigree
::AddProgeniesExistingAccessions
->new({
1254 chado_schema
=> $chado_schema,
1255 cross_name
=> $cross_name_key,
1256 progeny_names
=> \
@progenies,
1259 my $return = $adding_progenies->add_progenies_existing_accessions($overwrite_pedigrees);
1262 $error = "The progenies were not stored";
1265 if ($return->{error
}){
1266 $error = $return->{error
};
1270 $c->stash->{rest
} = { error
=> $error };
1276 my $md_row = $metadata_schema->resultset("MdMetadata")->create({create_person_id
=> $user_id});
1278 my $upload_file = CXGN
::UploadFile
->new();
1279 my $md5 = $upload_file->get_md5($archived_filename_with_path);
1280 my $md5checksum = $md5->hexdigest();
1281 my $file_row = $metadata_schema->resultset("MdFiles")->create({
1282 basename
=> basename
($archived_filename_with_path),
1283 dirname
=> dirname
($archived_filename_with_path),
1284 filetype
=> 'cross_progenies',
1285 md5checksum
=> $md5checksum,
1286 metadata_id
=> $md_row->metadata_id(),
1289 my $file_id = $file_row->file_id();
1290 # print STDERR "FILE ID =".Dumper($file_id)."\n";
1291 foreach my $cross_name (@all_crosses) {
1292 my $cross_experiment_type = CXGN
::Cross
->new({schema
=> $chado_schema, cross_name
=> $cross_name});
1293 my $experiment_id = $cross_experiment_type->get_nd_experiment_id_with_type_cross_experiment();
1294 # print STDERR "ND EXPERIMENT ID =".Dumper($experiment_id)."\n";
1295 my $nd_experiment_file = $phenome_schema->resultset("NdExperimentMdFiles")->create({
1296 nd_experiment_id
=> $experiment_id,
1297 file_id
=> $file_id,
1301 $c->stash->{rest
} = { success
=> 1 };
1304 sub upload_info
: Path
('/ajax/cross/upload_info') : ActionClass
('REST'){ }
1306 sub upload_info_POST
: Args
(0) {
1309 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
1310 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
1311 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
1312 my $dbh = $c->dbc->dbh;
1313 my $cross_info_upload = $c->req->upload('crossinfo_upload_file');
1314 my $additional_info_upload = $c->req->upload('additional_info_upload_file');
1319 if ($cross_info_upload) {
1320 $upload = $cross_info_upload;
1321 $upload_type = 'CrossInfoExcel';
1322 $data_type = 'crossing_metadata_json';
1324 if ($additional_info_upload) {
1325 $upload = $additional_info_upload;
1326 $upload_type = 'AdditionalInfoExcel';
1327 $data_type = 'cross_additional_info';
1329 # print STDERR "INFO UPLOAD =".Dumper($cross_info_upload)."\n";
1330 # print STDERR "ADDITIONAL INFO UPLOAD =".Dumper($additional_info_upload)."\n";
1331 # print STDERR "DATA TYPE =".Dumper($data_type)."\n";
1335 my $upload_original_name = $upload->filename();
1336 my $upload_tempfile = $upload->tempname;
1337 my $subdirectory = "cross_upload";
1338 my $archived_filename_with_path;
1344 my $time = DateTime
->now();
1345 my $timestamp = $time->ymd()."_".$time->hms();
1349 my $session_id = $c->req->param("sgn_session_id");
1352 my $dbh = $c->dbc->dbh;
1353 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
1354 if (!$user_info[0]){
1355 $c->stash->{rest
} = {error
=>'You must be logged in to upload cross info!'};
1358 $user_id = $user_info[0];
1359 $user_role = $user_info[1];
1360 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
1361 $user_name = $p->get_username;
1364 $c->stash->{rest
} = {error
=>'You must be logged in to upload cross info!'};
1367 $user_id = $c->user()->get_object()->get_sp_person_id();
1368 $user_name = $c->user()->get_object()->get_username();
1369 $user_role = $c->user->get_object->get_user_type();
1372 if (($user_role ne 'curator') && ($user_role ne 'submitter')) {
1373 $c->stash->{rest
} = {error
=>'Only a submitter or a curator can upload cross info'};
1377 my $uploader = CXGN
::UploadFile
->new({
1378 tempfile
=> $upload_tempfile,
1379 subdirectory
=> $subdirectory,
1380 archive_path
=> $c->config->{archive_path
},
1381 archive_filename
=> $upload_original_name,
1382 timestamp
=> $timestamp,
1383 user_id
=> $user_id,
1384 user_role
=> $user_role
1387 ## Store uploaded temporary file in arhive
1388 $archived_filename_with_path = $uploader->archive();
1389 $md5 = $uploader->get_md5($archived_filename_with_path);
1390 if (!$archived_filename_with_path) {
1391 $c->stash->{rest
} = {error
=> "Could not save file $upload_original_name in archive",};
1394 unlink $upload_tempfile;
1396 my $cross_properties_string = $c->config->{cross_properties
};
1397 my @properties = split ',', $cross_properties_string;
1398 my $cross_properties = \
@properties;
1400 my $cross_additional_info_string = $c->config->{cross_additional_info
};
1401 my @additional_info = split ',', $cross_additional_info_string;
1402 my $cross_additional_info = \
@additional_info;
1404 #parse uploaded file with appropriate plugin
1405 $parser = CXGN
::Pedigree
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $archived_filename_with_path, cross_properties
=> $cross_properties, cross_additional_info
=> $cross_additional_info);
1406 $parser->load_plugin($upload_type);
1407 $parsed_data = $parser->parse();
1408 # print STDERR "Dumper of parsed data:\t" . Dumper($parsed_data) . "\n";
1410 if (!$parsed_data) {
1411 my $return_error = '';
1413 if (!$parser->has_parse_errors() ){
1414 $c->stash->{rest
} = {error_string
=> "Could not get parsing errors"};
1416 $parse_errors = $parser->get_parse_errors();
1417 #print STDERR Dumper $parse_errors;
1419 foreach my $error_string (@
{$parse_errors->{'error_messages'}}){
1420 $return_error .= $error_string."<br>";
1423 $c->stash->{rest
} = {error_string
=> $return_error, missing_crosses
=> $parse_errors->{'missing_crosses'} };
1429 my %cross_info = %{$parsed_data};
1430 @all_crosses = keys %cross_info;
1431 foreach my $cross_name (keys %cross_info) {
1432 my %info_hash = %{$cross_info{$cross_name}};
1433 foreach my $info_type (keys %info_hash) {
1434 my $value = $info_hash{$info_type};
1435 my $cross_add_info = CXGN
::Pedigree
::AddCrossInfo
->new({
1436 chado_schema
=> $chado_schema,
1437 cross_name
=> $cross_name,
1440 data_type
=> $data_type
1443 $cross_add_info->add_info();
1445 if (!$cross_add_info->add_info()){
1446 $c->stash->{rest
} = {error_string
=> "Error saving info",};
1453 # print STDERR "FILE =".Dumper($archived_filename_with_path)."\n";
1454 my $md_row = $metadata_schema->resultset("MdMetadata")->create({create_person_id
=> $user_id});
1456 my $upload_file = CXGN
::UploadFile
->new();
1457 my $md5 = $upload_file->get_md5($archived_filename_with_path);
1458 my $md5checksum = $md5->hexdigest();
1459 my $file_row = $metadata_schema->resultset("MdFiles")->create({
1460 basename
=> basename
($archived_filename_with_path),
1461 dirname
=> dirname
($archived_filename_with_path),
1462 filetype
=> 'cross_info',
1463 md5checksum
=> $md5checksum,
1464 metadata_id
=> $md_row->metadata_id(),
1467 my $file_id = $file_row->file_id();
1468 # print STDERR "FILE ID =".Dumper($file_id)."\n";
1469 foreach my $cross_name (@all_crosses) {
1470 my $cross_experiment_type = CXGN
::Cross
->new({schema
=> $chado_schema, cross_name
=> $cross_name});
1471 my $experiment_id = $cross_experiment_type->get_nd_experiment_id_with_type_cross_experiment();
1472 # print STDERR "ND EXPERIMENT ID =".Dumper($experiment_id)."\n";
1473 my $nd_experiment_file = $phenome_schema->resultset("NdExperimentMdFiles")->create({
1474 nd_experiment_id
=> $experiment_id,
1475 file_id
=> $file_id,
1479 $c->stash->{rest
} = {success
=> "1",};
1483 sub upload_family_names
: Path
('/ajax/cross/upload_family_names') : ActionClass
('REST'){ }
1485 sub upload_family_names_POST
: Args
(0) {
1488 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
1489 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
1490 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
1491 my $dbh = $c->dbc->dbh;
1492 my $same_parents_upload = $c->req->upload('same_parents_file');
1493 my $reciprocal_parents_upload = $c->req->upload('reciprocal_parents_file');
1495 my $upload_original_name;
1496 my $upload_tempfile;
1499 if ($same_parents_upload) {
1500 $upload_original_name = $same_parents_upload->filename();
1501 $upload_tempfile = $same_parents_upload->tempname;
1502 $family_type = 'same_parents';
1505 if ($reciprocal_parents_upload) {
1506 $upload_original_name = $reciprocal_parents_upload->filename();
1507 $upload_tempfile = $reciprocal_parents_upload->tempname;
1508 $family_type = 'reciprocal_parents';
1513 my $subdirectory = "cross_upload";
1514 my $archived_filename_with_path;
1520 my $time = DateTime
->now();
1521 my $timestamp = $time->ymd()."_".$time->hms();
1526 # my $upload_file_type = "crosses excel";#get from form when more options are added
1527 my $session_id = $c->req->param("sgn_session_id");
1530 my $dbh = $c->dbc->dbh;
1531 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
1532 if (!$user_info[0]){
1533 $c->stash->{rest
} = {error
=>'You must be logged in to upload family names!'};
1536 $user_id = $user_info[0];
1537 $user_role = $user_info[1];
1538 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
1539 $user_name = $p->get_username;
1542 $c->stash->{rest
} = {error
=>'You must be logged in to upload family names!'};
1545 $user_id = $c->user()->get_object()->get_sp_person_id();
1546 $user_name = $c->user()->get_object()->get_username();
1547 $user_role = $c->user->get_object->get_user_type();
1550 if (($user_role ne 'curator') && ($user_role ne 'submitter')) {
1551 $c->stash->{rest
} = {error
=>'Only a submitter or a curator can upload family names'};
1555 my $uploader = CXGN
::UploadFile
->new({
1556 tempfile
=> $upload_tempfile,
1557 subdirectory
=> $subdirectory,
1558 archive_path
=> $c->config->{archive_path
},
1559 archive_filename
=> $upload_original_name,
1560 timestamp
=> $timestamp,
1561 user_id
=> $user_id,
1562 user_role
=> $user_role
1565 ## Store uploaded temporary file in arhive
1566 $archived_filename_with_path = $uploader->archive();
1567 $md5 = $uploader->get_md5($archived_filename_with_path);
1568 if (!$archived_filename_with_path) {
1569 $c->stash->{rest
} = {error
=> "Could not save file $upload_original_name in archive",};
1572 unlink $upload_tempfile;
1574 #parse uploaded file with appropriate plugin
1575 $parser = CXGN
::Pedigree
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $archived_filename_with_path);
1576 $parser->load_plugin('FamilyNameExcel');
1577 $parsed_data = $parser->parse();
1578 #print STDERR "Dumper of parsed data:\t" . Dumper($parsed_data) . "\n";
1581 my $return_error = '';
1583 if (!$parser->has_parse_errors() ){
1584 $c->stash->{rest
} = {error_string
=> "Could not get parsing errors"};
1586 $parse_errors = $parser->get_parse_errors();
1587 #print STDERR Dumper $parse_errors;
1589 foreach my $error_string (@
{$parse_errors->{'error_messages'}}){
1590 $return_error .= $error_string."<br>";
1593 $c->stash->{rest
} = {error_string
=> $return_error, missing_crosses
=> $parse_errors->{'missing_crosses'} };
1597 #add family name and associate with cross
1600 my %family_name_hash = %{$parsed_data};
1601 @all_crosses = keys %family_name_hash;
1602 foreach my $cross_name(keys %family_name_hash){
1603 my $family_name = $family_name_hash{$cross_name};
1605 my $family_name_add = CXGN
::Pedigree
::AddFamilyNames
->new({
1606 chado_schema
=> $chado_schema,
1607 phenome_schema
=> $phenome_schema,
1609 cross_name
=> $cross_name,
1610 family_name
=> $family_name,
1611 owner_name
=> $user_name,
1612 family_type
=> $family_type
1615 my $return = $family_name_add->add_family_name();
1618 $error = "Error adding family name";
1620 if ($return->{error
}){
1621 $error = $return->{error
};
1624 $c->stash->{rest
} = {error_string
=> $error };
1630 # print STDERR "FILE =".Dumper($archived_filename_with_path)."\n";
1631 my $md_row = $metadata_schema->resultset("MdMetadata")->create({create_person_id
=> $user_id});
1633 my $upload_file = CXGN
::UploadFile
->new();
1634 my $md5 = $upload_file->get_md5($archived_filename_with_path);
1635 my $md5checksum = $md5->hexdigest();
1636 my $file_row = $metadata_schema->resultset("MdFiles")->create({
1637 basename
=> basename
($archived_filename_with_path),
1638 dirname
=> dirname
($archived_filename_with_path),
1639 filetype
=> 'families',
1640 md5checksum
=> $md5checksum,
1641 metadata_id
=> $md_row->metadata_id(),
1644 my $file_id = $file_row->file_id();
1645 # print STDERR "FILE ID =".Dumper($file_id)."\n";
1646 foreach my $cross_name (@all_crosses) {
1647 my $cross_experiment_type = CXGN
::Cross
->new({schema
=> $chado_schema, cross_name
=> $cross_name});
1648 my $experiment_id = $cross_experiment_type->get_nd_experiment_id_with_type_cross_experiment();
1649 # print STDERR "ND EXPERIMENT ID =".Dumper($experiment_id)."\n";
1650 my $nd_experiment_file = $phenome_schema->resultset("NdExperimentMdFiles")->create({
1651 nd_experiment_id
=> $experiment_id,
1652 file_id
=> $file_id,
1656 $c->stash->{rest
} = {success
=> "1",};
1660 sub delete_cross
: Path
('/ajax/cross/delete') : ActionClass
('REST'){ }
1662 sub delete_cross_POST
: Args
(0) {
1667 $c->stash->{rest
} = { error
=> "You must be logged in to delete crosses" };
1670 if (!$c->user()->check_roles("curator")) {
1671 $c->stash->{rest
} = { error
=> "You do not have the correct role to delete crosses. Please contact us." };
1675 my $cross_stock_id = $c->req->param("cross_id");
1677 my $cross = CXGN
::Cross
->new( { schema
=> $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado'), cross_stock_id
=> $cross_stock_id });
1679 if (!$cross->cross_stock_id()) {
1680 $c->stash->{rest
} = { error
=> "No such cross exists. Cannot delete." };
1684 my $error = $cross->delete();
1686 print STDERR
"ERROR = $error\n";
1689 $c->stash->{rest
} = { error
=> "An error occurred attempting to delete a cross. ($@)" };
1693 $c->stash->{rest
} = { success
=> 1 };
1697 sub get_cross_transactions
:Path
('/ajax/cross/transactions') Args
(1) {
1700 my $cross_id = shift;
1702 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1703 my $cross_transaction_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'cross_transaction_json', 'stock_property')->cvterm_id();
1704 my $cross_transactions = $schema->resultset("Stock::Stockprop")->find({stock_id
=> $cross_id, type_id
=> $cross_transaction_cvterm});
1706 my $cross_transaction_string;
1707 my %cross_transaction_hash;
1708 my @all_transactions;
1710 if($cross_transactions){
1711 $cross_transaction_string = $cross_transactions->value();
1712 my $cross_transaction_ref = decode_json
$cross_transaction_string;
1713 %cross_transaction_hash = %{$cross_transaction_ref};
1714 foreach my $transaction_key (sort keys %cross_transaction_hash) {
1715 my $operator = $cross_transaction_hash{$transaction_key}{'Operator'};
1716 my $timestamp = $cross_transaction_hash{$transaction_key}{'Timestamp'};
1717 my $number_of_flowers = $cross_transaction_hash{$transaction_key}{'Number of Flowers'};
1718 my $number_of_fruits = $cross_transaction_hash{$transaction_key}{'Number of Fruits'};
1719 my $number_of_seeds = $cross_transaction_hash{$transaction_key}{'Number of Seeds'};
1720 push @all_transactions, [$transaction_key, $operator, $timestamp, $number_of_flowers, $number_of_fruits, $number_of_seeds];
1724 $c->stash->{rest
} = {data
=> \
@all_transactions};
1729 sub get_cross_additional_info
:Path
('/ajax/cross/additional_info') Args
(1) {
1732 my $cross_id = shift;
1733 my $schema = $c->dbic_schema("Bio::Chado::Schema");
1735 my $cross_additional_info_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'cross_additional_info', 'stock_property')->cvterm_id();
1736 my $cross_additional_info_rs = $schema->resultset("Stock::Stockprop")->find({stock_id
=> $cross_id, type_id
=> $cross_additional_info_cvterm});
1738 my $cross_info_json_string;
1739 if($cross_additional_info_rs){
1740 $cross_info_json_string = $cross_additional_info_rs->value();
1743 my $cross_info_hash ={};
1744 if($cross_info_json_string){
1745 $cross_info_hash = decode_json
$cross_info_json_string;
1748 my $cross_additional_info = $c->config->{cross_additional_info
};
1749 my @column_order = split ',',$cross_additional_info;
1752 foreach my $key (@column_order){
1753 push @row, $cross_info_hash->{$key};
1757 $c->stash->{rest
} = {data
=> \
@props};