Merge pull request #5243 from solgenomics/topic/observations_upload_catch_error
[sgn.git] / lib / SGN / Controller / AJAX / Dataset.pm
blobc2c55c551582b4deaa436cc24678877b84a6d603
2 package SGN::Controller::AJAX::Dataset;
4 use Moose;
6 BEGIN { extends 'Catalyst::Controller::REST' }
8 use File::Temp qw| tempfile tempdir |;
9 use Data::Dumper;
10 use JSON::Any;
11 use CXGN::Dataset;
12 use Text::CSV ("csv");
13 use strict;
14 use warnings;
16 __PACKAGE__->config(
17 default => 'application/json',
18 stash_key => 'rest',
19 map => { 'application/json' => 'JSON' },
22 sub store_dataset :Path('/ajax/dataset/save') Args(0) {
23 my $self = shift;
24 my $c = shift;
26 my $user;
27 if (!$c->user()) {
28 $c->stash->{rest} = { error => "Login required to perform requested action." };
29 return;
32 my %data;
34 my $dataset_name = $c->req->param("name");
35 my $dataset_description = $c->req->param("description");
37 my $user_id = $c->user()->get_object()->get_sp_person_id();
39 my $people_schema = $c->dbic_schema("CXGN::People::Schema", undef, $user_id);
40 if (CXGN::Dataset->exists_dataset_name($people_schema, $dataset_name)) {
41 $c->stash->{rest} = { error => "The dataset with name $dataset_name already exists. Please choose another name." };
42 return;
45 my $dataset = CXGN::Dataset->new( {
46 schema => $c->dbic_schema("Bio::Chado::Schema", undef, $user_id),
47 people_schema => $people_schema,
48 });
50 $dataset->sp_person_id($user_id);
51 $dataset->name($dataset_name);
52 $dataset->description($dataset_description);
54 foreach my $type (qw | trials accessions years locations plots traits breeding_programs genotyping_protocols genotyping_projects trial_types trial_designs category_order |) {
55 #print STDERR "Storing data: $type\n";
57 my $json = $c->req->param($type);
58 if ($json) {
59 my $obj = JSON::Any->jsonToObj($json);
60 $dataset->$type($obj);
64 $dataset->store();
66 $c->stash->{rest} = { message => "Stored Dataset Successfully!" };
69 sub store_outliers_in_dataset :Path('/ajax/dataset/store_outliers') Args(1) {
70 my $self = shift;
71 my $c = shift;
72 my $dataset_id = shift;
73 my $string_outliers = $c->req->param('outliers');
74 my $string_outlier_cutoffs = $c->req->param('outlier_cutoffs');
76 my @outliers = split(',',$string_outliers);
77 my @outlier_cutoffs = split(',', $string_outlier_cutoffs);
78 my $dataset = CXGN::Dataset->new(
80 schema => $c->dbic_schema("Bio::Chado::Schema"),
81 people_schema => $c->dbic_schema("CXGN::People::Schema"),
82 sp_dataset_id => $dataset_id,
83 outliers => \@outliers,
84 outlier_cutoffs => \@outlier_cutoffs
85 });
88 $dataset->store();
89 $c->stash->{rest} = { success => 1 };
93 sub retrieve_outliers_from_dataset :Path('/ajax/dataset/retrieve_outliers') Args(1) {
94 my $self = shift;
95 my $c = shift;
96 my $dataset_id = shift;
98 my $dataset = CXGN::Dataset->new(
100 schema => $c->dbic_schema("Bio::Chado::Schema"),
101 people_schema => $c->dbic_schema("CXGN::People::Schema"),
102 sp_dataset_id => $dataset_id,
105 my $outliers = $dataset->outliers();
107 $c->stash->{rest} = { outliers => $outliers };
110 sub get_rosners_test_outliers :Path('/ajax/dataset/rosner_test') Args(1) {
111 my $self = shift;
112 my $c = shift;
113 my $dataset_id = shift;
114 my $dataset_trait = $c->req->param('dataset_trait');
116 print STDERR "dataset_trait: $dataset_trait";
117 my $dataset = CXGN::Dataset->new({
118 schema => $c->dbic_schema("Bio::Chado::Schema"),
119 people_schema => $c->dbic_schema("CXGN::People::Schema"),
120 sp_dataset_id => $dataset_id,
121 include_phenotype_primary_key => 1,
124 my $phenotypes_data_ref = $dataset->retrieve_phenotypes();
125 my @columns = @{$phenotypes_data_ref->[0]};
126 # print STDERR "columns: ", join(", ", @columns);
128 my ($trait_index) = grep { @columns[$_] eq $dataset_trait } (0 .. scalar @columns -1);
129 my ($trait_id_index) = grep { @columns[$_] eq "${dataset_trait}_phenotype_id" } (0 .. scalar @columns -1);
131 $c->tempfiles_subdir("rosners_files");
132 my ($trait_file_path, $temp_file) = $c->tempfile(TEMPLATE=>"rosners_files/trait_XXXXX", SUFFIX => '.csv');
133 my ($stat_file_path, $stat_file) = $c->tempfile(TEMPLATE=>"rosners_files/stat_XXXXX", SUFFIX => '.csv');
135 my $csv = Text::CSV->new ({ binary => 1});
137 open my $fh, ">:encoding(utf8)", $trait_file_path or die "$trait_file_path: $!";
138 foreach my $row (@$phenotypes_data_ref) {
139 $csv->say ($fh, [$row->[$trait_index], $row->[$trait_id_index]]);
141 close $fh;
143 # run cluster with R
144 my $cmd = CXGN::Tools::Run->new({
145 backend => $c->config->{backend},
146 submit_host=>$c->config->{cluster_host},
147 temp_base => $c->config->{cluster_shared_tempdir} . "/rosners_files",
148 queue => $c->config->{'web_cluster_queue'},
149 do_cleanup => 0,
150 # don't block and wait if the cluster looks full
151 max_cluster_jobs => 1_000_000_000,
154 $cmd->run_cluster(
155 "Rscript ",
156 $c->config->{basepath} . "/R/dataset/rosner_test.R",
157 $trait_file_path,
158 $stat_file_path
160 $cmd->alive;
161 $cmd->is_cluster(1);
162 $cmd->wait;
164 # print STDERR Dumper $stat_file_path;
165 my $aoa = csv (in => $stat_file_path); # as array of hash
167 $c->stash->{rest} = {
168 message => "Rosners TEST Successfully!",
169 dataset_id => $dataset_id,
170 dataset_trait => $dataset_trait,
171 data => \@columns,
172 index => $trait_index,
173 phenotype_id_index => $trait_id_index,
174 file => $aoa,
178 sub retrieve_datasets_by_user :Path('/ajax/dataset/by_user') Args(0) {
179 my $self = shift;
180 my $c = shift;
182 my $user = $c->user();
183 if (!$user) {
184 $c->stash->{rest} = { error => "No logged in user to display dataset information for." };
185 return;
188 my $sp_person_id = $c->user() ? $c->user()->get_object->get_sp_person_id() : undef;
189 my $datasets = CXGN::Dataset->get_datasets_by_user(
190 $c->dbic_schema("CXGN::People::Schema", undef, $sp_person_id),
191 $sp_person_id
194 $c->stash->{rest} = $datasets;
197 sub get_datasets_by_user_html :Path('/ajax/dataset/by_user_html') Args(0) {
198 my $self = shift;
199 my $c = shift;
201 my $user = $c->user();
202 if (!$user) {
203 $c->stash->{rest} = { error => "No logged in user to display dataset information for." };
204 return;
207 my $sp_person_id = $c->user() ? $c->user()->get_object->get_sp_person_id() : undef;
209 my $datasets = CXGN::Dataset->get_datasets_by_user(
210 $c->dbic_schema("CXGN::People::Schema", undef, $sp_person_id),
211 $sp_person_id
214 my @result;
215 foreach (@$datasets) {
216 my @res;
217 push @res, ("<a href=\"/dataset/$_->[0]\">$_->[1]</a>", $_->[2]);
218 push @result , \@res;
220 $c->stash->{rest} = { data => \@result };
223 sub get_datasets_public :Path('/ajax/dataset/get_public') {
224 my $self = shift;
225 my $c = shift;
227 my $sp_person_id = $c->user() ? $c->user->get_object()->get_sp_person_id() : undef;
229 my $datasets = CXGN::Dataset->get_datasets_public(
230 $c->dbic_schema("CXGN::People::Schema", undef, $sp_person_id)
233 $c->stash->{rest} = $datasets;
236 sub set_datasets_public :Path('/ajax/dataset/set_public') Args(1) {
237 my $self = shift;
238 my $c = shift;
239 my $dataset_id = shift;
241 my $user = $c->user();
242 if (!$user) {
243 $c->stash->{rest} = { error => "No logged in user error." };
244 return;
247 my $logged_in_user = $c->user()->get_object()->get_sp_person_id();
249 my $dataset = CXGN::Dataset->new(
251 schema => $c->dbic_schema("Bio::Chado::Schema", undef, $logged_in_user),
252 people_schema => $c->dbic_schema("CXGN::People::Schema", undef, $logged_in_user),
253 sp_dataset_id=> $dataset_id,
255 print STDERR "Dataset owner: ".$dataset->sp_person_id.", logged in: $logged_in_user\n";
256 if ($dataset->sp_person_id() != $logged_in_user) {
257 $c->stash->{rest} = { error => "Only the owner can change a dataset" };
258 return;
260 print STDERR "set public dataset_id $dataset_id\n";
261 my $error = $dataset->set_dataset_public();
263 if ($error) {
264 $c->stash->{rest} = { error => $error };
265 } else {
266 $c->stash->{rest} = { success => 1 };
270 sub set_datasets_private :Path('/ajax/dataset/set_private') Args(1) {
271 my $self = shift;
272 my $c = shift;
273 my $dataset_id = shift;
275 my $user = $c->user();
276 if (!$user) {
277 $c->stash->{rest} = { error => "No logged in user error." };
278 return;
281 my $logged_in_user = $c->user()->get_object()->get_sp_person_id();
283 my $dataset = CXGN::Dataset->new(
285 schema => $c->dbic_schema("Bio::Chado::Schema", undef, $logged_in_user),
286 people_schema => $c->dbic_schema("CXGN::People::Schema", undef, $logged_in_user),
287 sp_dataset_id=> $dataset_id,
289 print STDERR "Dataset owner: ".$dataset->sp_person_id.", logged in: $logged_in_user\n";
290 if ($dataset->sp_person_id() != $logged_in_user) {
291 $c->stash->{rest} = { error => "Only the owner can change a dataset" };
292 return;
294 print STDERR "set private dataset_id $dataset_id\n";
295 my $error = $dataset->set_dataset_private();
297 if ($error) {
298 $c->stash->{rest} = { error => $error };
299 } else {
300 $c->stash->{rest} = { success => 1 };
304 sub update_description :Path('/ajax/dataset/update_description') Args(1) {
305 my $self = shift;
306 my $c = shift;
307 my $dataset_id = shift;
309 my $dataset_description = $c->req->param("description");
311 my $user = $c->user();
312 if (!$user) {
313 $c->stash->{rest} = { error => "No logged in user error." };
314 return;
317 my $logged_in_user = $c->user()->get_object()->get_sp_person_id();
319 my $dataset = CXGN::Dataset->new(
321 schema => $c->dbic_schema("Bio::Chado::Schema", undef, $logged_in_user),
322 people_schema => $c->dbic_schema("CXGN::People::Schema", undef, $logged_in_user),
323 sp_dataset_id=> $dataset_id,
325 $dataset->description($dataset_description);
326 print STDERR "Dataset owner: ".$dataset->sp_person_id.", logged in: $logged_in_user\n";
327 if ($dataset->sp_person_id() != $logged_in_user) {
328 $c->stash->{rest} = { error => "Only the owner can change a dataset" };
329 return;
331 my $error = $dataset->update_description($dataset_description);
333 if ($error) {
334 $c->stash->{rest} = { error => $error };
335 } else {
336 $c->stash->{rest} = { success => 1 };
340 sub get_dataset :Path('/ajax/dataset/get') Args(1) {
341 my $self = shift;
342 my $c = shift;
343 my $dataset_id = shift;
345 my $sp_person_id = $c->user() ? $c->user->get_object()->get_sp_person_id() : undef;
347 my $dataset = CXGN::Dataset->new(
349 schema => $c->dbic_schema("Bio::Chado::Schema", undef, $sp_person_id),
350 people_schema => $c->dbic_schema("CXGN::People::Schema", undef, $sp_person_id),
351 sp_dataset_id=> $dataset_id,
354 my $dataset_data = $dataset->get_dataset_data();
356 $c->stash->{rest} = { dataset => $dataset_data };
360 sub retrieve_dataset_dimension :Path('/ajax/dataset/retrieve') Args(2) {
361 my $self = shift;
362 my $c = shift;
363 my $dataset_id = shift;
364 my $dimension = shift;
365 my $include_phenotype_primary_key = $c->req->param('include_phenotype_primary_key');
367 my $dataset = CXGN::Dataset->new(
369 schema => $c->dbic_schema("Bio::Chado::Schema"),
370 people_schema => $c->dbic_schema("CXGN::People::Schema"),
371 sp_dataset_id=> $dataset_id,
372 include_phenotype_primary_key => $include_phenotype_primary_key,
376 my $dimension_data;
377 my $function_name = 'retrieve_'.$dimension;
378 if ($dataset->can($function_name)) {
380 $dimension_data = $dataset->$function_name();
382 else {
383 $c->stash->{rest} = { error => "The specified dimension '$dimension' does not exist" };
384 return;
387 $c->stash->{rest} = { dataset_id => $dataset_id,
388 $dimension => $dimension_data,
392 sub delete_dataset :Path('/ajax/dataset/delete') Args(1) {
393 my $self = shift;
394 my $c = shift;
395 my $dataset_id = shift;
397 if (!$c->user()) {
398 $c->stash->{rest} = { error => "Deleting datasets requires login" };
399 return;
402 my $logged_in_user = $c->user()->get_object()->get_sp_person_id();
404 my $dataset = CXGN::Dataset->new(
406 schema => $c->dbic_schema("Bio::Chado::Schema", undef, $logged_in_user),
407 people_schema => $c->dbic_schema("CXGN::People::Schema", undef, $logged_in_user),
408 sp_dataset_id=> $dataset_id,
411 # print STDERR "Dataset owner: ".$dataset->sp_person_id.", logged in: $logged_in_user\n";
412 if ($dataset->sp_person_id() != $logged_in_user) {
413 $c->stash->{rest} = { error => "Only the owner can delete a dataset" };
414 return;
417 my $error = $dataset->delete();
419 if ($error) {
420 $c->stash->{rest} = { error => $error };
422 else {
423 $c->stash->{rest} = { success => 1 };