5 upload_multiple_trial_design.pl
9 upload_multiple_trial_design.pl -H [dbhost] -D [dbname] -P [dbpass] -w [basepath] -U [dbuser] -i infile -un [username] -e [email address]
11 =head1 COMMAND-LINE OPTIONS
13 -H host name (required) Ex: "breedbase_db"
14 -D database name (required) Ex: "breedbase"
15 -U database username Ex: "postgres"
16 -P database userpass Ex: "postgres"
17 -w basepath (required) Ex: /home/production/cxgn/sgn
18 -i path to infile (required)
19 -un username of uploader (required)
20 -e email address of the user
21 if loading trial data from metadata file, phenotypes + layout from infile
25 perl bin/upload_multiple_trial_design.pl -H breedbase_db -D breedbase -U postgres -P postgres -w /home/cxgn/sgn/ -un janedoe -i ~/Desktop/test_multi.xlsx -e 'sk2783@cornell.edu' -iw
27 This script will parse and validate the input file. If there are any warnings or errors during validation it will send a error message to the provided email. It will print any errors and warnings to the console.
28 If there are no errors or warnings (or warnings are ignored) during validation it will then store the data.
29 The input file should be any file supported by the CXGN::File::Parse class.
33 Srikanth (sk2783@cornell.edu)
39 use Bio
::Chado
::Schema
;
40 use CXGN
::DB
::InsertDBH
;
44 use CXGN
::Trial
; # add project metadata
45 use CXGN
::Trial
::ParseUpload
;
46 use CXGN
::Trial
::TrialCreate
;
48 use CXGN
::TrialStatus
;
50 my ( $help, $dbhost, $dbname, $basepath, $dbuser, $dbpass, $infile, $username, $email_address, $ignore_warnings);
52 'dbhost|H=s' => \
$dbhost,
53 'dbname|D=s' => \
$dbname,
54 'dbuser|U=s' => \
$dbuser,
55 'dbpass|P=s' => \
$dbpass,
56 'basepath|w=s' => \
$basepath,
58 'user|un=s' => \
$username,
59 'email|e=s' => \
$email_address,
60 'ignore_warnings|iw!' => \
$ignore_warnings,
63 pod2usage
(1) if $help;
64 if (!$infile || !$username || !$basepath || !$dbname || !$dbhost ) {
65 pod2usage
({ -msg
=> 'Error. Missing options!', -verbose
=> 1, -exitval
=> 1 });
68 # Lists of encountered errors and warnings
72 # Connect to databases
74 if ($dbpass && $dbuser) {
76 "dbi:Pg:database=$dbname;host=$dbhost",
79 {AutoCommit
=> 1, RaiseError
=> 1}
83 $dbh = CXGN
::DB
::InsertDBH
->new({
86 dbargs
=> {AutoCommit
=> 1, RaiseError
=> 1}
89 my $chado_schema = Bio
::Chado
::Schema
->connect(sub { $dbh }, { on_connect_do
=> ['SET search_path TO public, sgn, metadata, phenome;'] });
90 print STDOUT
"Database connection ok!\n";
93 my $validation_coderef = sub {
94 # Parse uploaded file with appropriate plugin
95 my $parser = CXGN
::Trial
::ParseUpload
->new(chado_schema
=> $chado_schema, filename
=> $infile);
96 $parser->load_plugin('MultipleTrialDesignGeneric');
97 $parsed_data = $parser->parse();
99 # Parser has errors, print error messages and quit
100 if ($parser->has_parse_errors()) {
101 my $errors = $parser->get_parse_errors();
102 foreach (@
{$errors->{'error_messages'}}) {
108 # Parser has warnings, print warning messages and quit unless we're ignoring warnings
109 if ($parser->has_parse_warnings()) {
110 unless ($ignore_warnings) {
111 my $warnings = $parser->get_parse_warnings();
112 foreach (@
{$warnings->{'warning_messages'}}) {
121 $chado_schema->txn_do($validation_coderef);
126 # Check for parsed data
127 finish
("There is no parsed data from the input file!") if !$parsed_data;
130 my $sp_person_id = CXGN
::People
::Person
->get_person_by_username($dbh, $username);
131 finish
("User not found in database for username $username!") if !$sp_person_id;
133 # Create and Save Trials
134 my %all_designs = %{$parsed_data};
137 for my $trial_name ( keys %all_designs ) {
138 my $trial_design = $all_designs{$trial_name};
139 my %trial_info_hash = (
140 chado_schema
=> $chado_schema,
142 owner_id
=> $sp_person_id,
143 trial_year
=> $trial_design->{'year'},
144 trial_description
=> $trial_design->{'description'},
145 trial_location
=> $trial_design->{'location'},
146 trial_name
=> $trial_name,
147 design_type
=> $trial_design->{'design_type'},
148 design
=> $trial_design->{'design_details'},
149 program
=> $trial_design->{'breeding_program'},
150 upload_trial_file
=> $infile,
151 operator
=> $username,
152 owner_id
=> $sp_person_id
154 my $entry_numbers = $trial_design->{'entry_numbers'};
156 if ($trial_design->{'trial_type'}){
157 $trial_info_hash{trial_type
} = $trial_design->{'trial_type'};
159 if ($trial_design->{'plot_width'}){
160 $trial_info_hash{plot_width
} = $trial_design->{'plot_width'};
162 if ($trial_design->{'plot_length'}){
163 $trial_info_hash{plot_length
} = $trial_design->{'plot_length'};
165 if ($trial_design->{'field_size'}){
166 $trial_info_hash{field_size
} = $trial_design->{'field_size'};
168 if ($trial_design->{'planting_date'}){
169 $trial_info_hash{planting_date
} = $trial_design->{'planting_date'};
171 if ($trial_design->{'harvest_date'}){
172 $trial_info_hash{harvest_date
} = $trial_design->{'harvest_date'};
174 if ($trial_design->{'transplanting_date'}){
175 $trial_info_hash{transplanting_date
} = $trial_design->{'transplanting_date'};
177 my $trial_create = CXGN
::Trial
::TrialCreate
->new(\
%trial_info_hash);
178 my $current_save = $trial_create->save_trial();
180 if ($current_save->{error
}){
181 $chado_schema->txn_rollback();
182 finish
($current_save->{'error'});
183 } elsif ($current_save->{'trial_id'}) {
184 my $trial_id = $current_save->{'trial_id'};
185 my $time = DateTime
->now();
186 my $timestamp = $time->ymd();
187 my $calendar_funcs = CXGN
::Calendar
->new({});
188 my $formatted_date = $calendar_funcs->check_value_format($timestamp);
189 my $upload_date = $calendar_funcs->display_start_date($formatted_date);
190 $saved_trials{$trial_id} = $trial_name;
193 $trial_activity{'Trial Uploaded'}{'user_id'} = $sp_person_id;
194 $trial_activity{'Trial Uploaded'}{'activity_date'} = $upload_date;
196 my $trial_activity_obj = CXGN
::TrialStatus
->new({ bcs_schema
=> $chado_schema });
197 $trial_activity_obj->trial_activities(\
%trial_activity);
198 $trial_activity_obj->parent_id($trial_id);
199 my $activity_prop_id = $trial_activity_obj->store();
202 # save entry numbers, if provided
203 if ( $entry_numbers && scalar(keys %$entry_numbers) > 0 && $current_save->{'trial_id'} ) {
204 my %entry_numbers_prop;
205 my @stock_names = keys %$entry_numbers;
207 # Convert stock names from parsed trial template to stock ids for data storage
208 my $stocks = $chado_schema->resultset('Stock::Stock')->search({ uniquename
=>{-in=>\
@stock_names} });
209 while (my $s = $stocks->next()) {
210 $entry_numbers_prop{$s->stock_id} = $entry_numbers->{$s->uniquename};
213 # Lookup synonyms of accession names
214 my $synonym_cvterm_id = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'stock_synonym', 'stock_property')->cvterm_id();
215 my $acc_synonym_rs = $chado_schema->resultset("Stock::Stock")->search({
216 'me.is_obsolete' => { '!=' => 't' },
217 'stockprops.value' => { -in => \
@stock_names},
218 'stockprops.type_id' => $synonym_cvterm_id
219 },{join => 'stockprops', '+select'=>['stockprops.value'], '+as'=>['synonym']});
220 while (my $r=$acc_synonym_rs->next) {
221 if ( exists($entry_numbers->{$r->get_column('synonym')}) ) {
222 $entry_numbers_prop{$r->stock_id} = $entry_numbers->{$r->get_column('synonym')};
226 # store entry numbers
227 my $trial = CXGN
::Trial
->new({ bcs_schema
=> $chado_schema, trial_id
=> $current_save->{'trial_id'} });
228 $trial->set_entry_numbers(\
%entry_numbers_prop);
235 $chado_schema->txn_do($coderef);
244 push @errors, $error if $error;
246 # Print errors and warnings to STDERR
248 print STDERR
"ERROR: $_\n";
250 foreach (@warnings) {
251 print STDERR
"WARNING: $_\n";
254 # Send email message, if requested
255 # Exit the script: 0 = success, 1 = errors, 2 = warnings
256 if ( scalar(@errors) > 0 ) {
257 if ( $email_address ) {
258 my $email_subject = "Multiple Trial Designs upload failed";
259 my $email_body = "Dear $username,\n\nThere were one or more errors in uploading your trials:\n\n";
260 foreach my $error (@errors) {
261 $error =~ s/<[^>]*>//g;
262 $email_body .= "$error\n";
264 $email_body .= "\nYou will need to fix the errors and upload the corrected file. Thank you\nHave a nice day\n\n";
265 CXGN
::Contact
::send_email
($email_subject, $email_body, $email_address);
269 if ( scalar(@warnings) > 0 ) {
270 if ( $email_address ) {
271 my $email_subject = "Multiple Trial Designs upload failed";
272 my $email_body = "Dear $username,\n\nThere were one or more warnings in uploading your trials and the option to ignore warnings was not enabled. The warnings include:\n\n";
273 foreach my $warning (@warnings) {
274 $warning =~ s/<[^>]*>//g;
275 $email_body .= "$warning\n";
277 $email_body .= "\nYou will need to either fix the warnings and upload the corrected file or upload the same file with the option to ignore warnings enabled. Thank you\nHave a nice day\n\n";
278 CXGN
::Contact
::send_email
($email_subject, $email_body, $email_address);
283 my $bs = CXGN
::BreederSearch
->new({ dbh
=>$dbh, dbname
=>$dbname });
284 my $refresh = $bs->refresh_matviews($dbhost, $dbname, $dbuser, $dbpass, 'all_but_genoview', 'concurrent', $basepath);
286 if ( $email_address ) {
287 my $email_subject = "Multiple Trial Designs upload successful";
288 my $email_body = "Dear $username,\n\nCongratulations, all the multiple trial designs have been successfully uploaded into the database\n\nThank you\nHave a nice day\n\n";
289 CXGN
::Contact
::send_email
($email_subject, $email_body, $email_address);