5 SGN::Image - SGN Images
9 This class provides database access and store functions as well as
10 image upload and certain image manipulation functions, such as image
11 file type conversion and image resizing; and functions to associate
12 tags with the image. Note that this was forked off from the insitu
13 image object. The insitu database needs to be re-factored to use this
16 The philosophy of the image object has changed slightly from the
17 Insitu::Image object. It now stores the images in a directory
18 specified by the conf object parameter "static_datasets_dir" plus
19 the conf parameter "image_dir" plus the directory name "image_files"
20 for the production server and the directory "image_files_sandbox" for
21 the test server. In those directories, it creates a subdirectory for
22 each image, with the subdirectory name being the corresponding image
23 id. In that directory are then several files, the originial image file
24 with the orignial name, the converted image into jpg in the standard
25 image sizes: large, medium, small and thumbnail with the names:
26 large.jpg, medium.jpg, small.jpg and thumbnail.jpg . All other
27 metadata about the image is stored in the database.
31 Lukas Mueller (lam87@cornell.edu)
32 Naama Menda (nm249@cornell.edu)
35 =head1 MEMBER FUNCTIONS
37 The following functions are provided in this class:
44 use File
::Path
'make_path';
45 use File
::Temp qw
/ tempfile tempdir /;
46 use File
::Copy qw
/ copy move /;
47 use File
::Basename qw
/ basename /;
49 use CXGN
::DB
::Connection
;
51 use CXGN
::Metadata
::Metadbdata
;
52 use SGN
::Model
::Cvterm
;
55 use CatalystX
::GlobalContext
'$c';
57 use base qw
| CXGN
::Image
|;
61 Usage: my $image = SGN::Image->new($dbh)
64 Args: a database handle, optional identifier
65 Side Effects: an empty object is returned.
66 a database connection is established.
72 my ( $class, $dbh, $image_id, $context ) = @_;
75 my $self = $class->SUPER::new
(
76 dbh
=> $dbh || $context->dbc->dbh,
77 image_id
=> $image_id,
78 image_dir
=> $context->get_conf('static_datasets_path')."/".$context->get_conf('image_dir'),
81 $self->config( $context );
90 Usage: $self->get_image_url($size)
91 Desc: get the url for the image with a given size
92 Ret: a url for the image
93 Args: size (large, medium, small, thumbnail, original)
103 if( $self->config->test_mode && ! -e
$self->get_filename($size) ) {
104 # for performance, only try to stat the file if running in
105 # test mode. doing lots of file stats over NFS can actually be
107 return '/img/image_temporarily_unavailable.png';
110 my $url = join '/', (
112 $self->config()->get_conf('static_datasets_url'),
113 $self->config()->get_conf('image_dir'),
114 $self->get_filename($size, 'partial'),
122 Usage: $image->process_image($filename, "stock", 234);
123 Desc: creates the image and associates it to the type and type_id
125 Args: filename, type (experiment, stock, fish, locus, organism) , type_id
126 Side Effects: Calls the relevant $image->associate_$type function
133 my ($filename, $type, $type_id, $linking_table_type_id) = @_;
135 $self->SUPER::process_image
($filename);
137 if ( $type eq "experiment" ) {
138 #print STDERR "Associating experiment $type_id...\n";
139 $self->associate_experiment($type_id);
141 elsif ( $type eq "stock" ) {
142 #print STDERR "Associating stock $type_id...\n";
143 $self->associate_stock($type_id);
145 elsif ( $type eq "fish" ) {
146 #print STDERR "Associating to fish experiment $type_id\n";
147 $self->associate_fish_result($type_id);
149 elsif ( $type eq "locus" ) {
150 #print STDERR "Associating to locus $type_id\n";
151 $self->associate_locus($type_id);
153 elsif ( $type eq "organism" ) {
154 $self->associate_organism($type_id);
156 elsif ( $type eq "cvterm" ) {
157 $self->associate_cvterm($type_id);
159 elsif ( $type eq "project" ) {
160 $self->associate_project($type_id, $linking_table_type_id);
163 elsif ( $type eq "test") {
164 # need to return something to make this function happy
169 warn "type $type is not recognized as one of the legal types. Not associating image with any object. Please check if your loading script links the image with an sgn object! \n";
174 =head2 config, context, _app
176 Get the Catalyst context object we are running with.
181 my ($self,$obj) = @_;
183 $self->{configuration_object
} = $obj if $obj;
185 return $self->{configuration_object
};
190 =head2 get_img_src_tag
195 Args: "large" | "medium" | "small" | "thumbnail" | "original" | "tiny"
202 sub get_img_src_tag
{
205 my $url = $self->get_image_url($size);
206 my $name = $self->get_name() || '';
207 if ( $size && $size eq "original" ) {
209 my $static = $self->config()->get_conf("static_datasets_url");
214 . "\"><span class=\"glyphicon glyphicon-floppy-save\" alt=\""
218 elsif ( $size && $size eq "tiny" ) {
222 . "\" width=\"20\" height=\"15\" border=\"0\" alt=\""
230 . "\" border=\"0\" alt=\""
236 =head2 get_temp_filename
247 sub get_temp_filename
{
249 return $self->{temp_filename
};
253 =head2 set_temp_filename
264 sub set_temp_filename
{
266 $self->{temp_filename
} = shift;
269 =head2 apache_upload_image
273 Usage: my $temp_file_name = $image->apache_upload_image($apache_upload_object);
275 Ret: the name of the intermediate tempfile that can be
276 used to access down the road.
277 Args: an apache upload object
278 Side Effects: generates an intermediate temp file from an apache request
279 that can be handled more easily. Adds the remote IP addr to the
280 filename so that different uploaders don\'t clobber but
281 allows only one upload per remote addr at a time.
282 Errors: change 11/30/07 - removes temp file if already exists
283 # returns -1 if the intermediate temp file already exists.
284 # this probably means that the submission button was hit twice
285 # and that an upload is already in progress.
290 sub apache_upload_image
{
293 ### deanx jan 03 2007
294 # Adjust File name if using Windows IE - it sends whole paht; drive letter, path, and filename
296 if ( $ENV{HTTP_USER_AGENT
} =~ /msie/i ) {
297 my ( $directory, $filename ) = $upload->filename =~ m/(.*\\)(.*)$/;
298 $upload_filename = $filename;
301 $upload_filename = $upload->filename;
304 my $upload_fh = $upload->fh;
307 $self->config()->get_conf("basepath") . "/"
308 . $self->config()->get_conf("tempfiles_subdir")
310 . $ENV{REMOTE_ADDR
} . "-"
313 my $ret_temp_file = $self->upload_image($temp_file, $upload_fh);
314 return $ret_temp_file;
318 sub upload_fieldbook_zipfile
{
320 my $image_zip = shift;
322 my $c = $self->config();
324 my $schema = $c->dbic_schema("Bio::Chado::Schema");
325 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
326 my $dbh = $schema->storage->dbh;
327 my $archived_zip = CXGN
::ZipFile
->new(archived_zipfile_path
=>$image_zip);
328 my $file_members = $archived_zip->file_members();
330 $error_status = 'Could not read your zipfile. Is is .zip format?</br></br>';
331 return $error_status;
333 my $plot_cvterm_id = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'plot', 'stock_type')->cvterm_id();
334 my $plant_cvterm_id = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'plant', 'stock_type')->cvterm_id();
336 foreach (@
$file_members) {
337 my $image = SGN
::Image
->new( $dbh, undef, $c );
338 #print STDERR Dumper $_;
339 my $img_name = substr($_->fileName(), 0, -24);
340 $img_name =~ s/^.*photos\///;
341 my $stock = $schema->resultset("Stock::Stock")->find( { uniquename
=> $img_name, 'me.type_id' => [$plot_cvterm_id, $plant_cvterm_id] } );
342 my $stock_id = $stock->stock_id;
344 my $temp_file = $image->upload_zipfile_images($_);
346 #Check if image already stored in database
347 my $md5checksum = $image->calculate_md5sum($temp_file);
348 #print STDERR "MD5: $md5checksum\n";
349 my $md_image = $metadata_schema->resultset("MdImage")->search({md5sum
=>$md5checksum})->count();
350 #print STDERR "Count: $md_image\n";
352 print STDERR Dumper
"Image $temp_file has already been added to the database and will not be added again.";
353 $error_status .= "Image $temp_file has already been added to the database and will not be added again.<br/><br/>";
355 $image->set_sp_person_id($user_id);
356 my $ret = $image->process_image($temp_file, 'stock', $stock_id);
358 $error_status .= "Image processing for $temp_file did not work. Image not associated to stock_id $stock_id.<br/><br/>";
362 return $error_status;
365 sub upload_phenotypes_associated_images_zipfile
{
367 my $image_zip = shift;
369 my $image_observation_unit_hash = shift;
370 my $image_type_name = shift;
371 print STDERR
"Doing upload_phenotypes_associated_images_zipfile\n";
372 my $c = $self->config();
373 my $schema = $c->dbic_schema("Bio::Chado::Schema");
374 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
375 my $dbh = $schema->storage->dbh;
376 my $archived_zip = CXGN
::ZipFile
->new(archived_zipfile_path
=>$image_zip);
377 my $file_members = $archived_zip->file_members();
379 return {error
=> 'Could not read your zipfile. Is is .zip format?</br></br>'};
382 my $linking_table_type_id = SGN
::Model
::Cvterm
->get_cvterm_row($schema, $image_type_name, 'project_md_image')->cvterm_id();
384 my $image_tag_id = CXGN
::Tag
::exists_tag_named
($schema->storage->dbh, $image_type_name);
385 if (!$image_tag_id) {
386 my $image_tag = CXGN
::Tag
->new($schema->storage->dbh);
387 $image_tag->set_name($image_type_name);
388 $image_tag->set_description('Upload phenotype spreadsheet with associated images: '.$image_type_name);
389 $image_tag->set_sp_person_id($user_id);
390 $image_tag_id = $image_tag->store();
392 my $image_tag = CXGN
::Tag
->new($schema->storage->dbh, $image_tag_id);
394 my %observationunit_stock_id_image_id;
395 foreach (@
$file_members) {
396 my $image = SGN
::Image
->new( $dbh, undef, $c );
397 my $img_name = basename
($_->fileName());
400 if ($img_name =~ m/(.*)(\.(?!\.).*)$/) { # extension is what follows last .
404 my $stock_id = $image_observation_unit_hash->{$img_name}->{stock_id
};
405 my $project_id = $image_observation_unit_hash->{$img_name}->{project_id
};
406 if ($stock_id && $project_id) {
407 my $temp_file = $image->upload_zipfile_images($_);
409 #Check if image already stored in database
410 $image = SGN
::Image
->new( $schema->storage->dbh, undef, $c );
411 my $q = "SELECT md_image.image_id FROM metadata.md_image AS md_image
412 JOIN phenome.project_md_image AS project_md_image ON(project_md_image.image_id = md_image.image_id)
413 JOIN phenome.stock_image AS stock_image ON (stock_image.image_id = md_image.image_id)
414 WHERE md_image.obsolete = 'f' AND project_md_image.type_id = $linking_table_type_id AND project_md_image.project_id = $project_id AND stock_image.stock_id = $stock_id AND md_image.original_filename = '$basename';";
415 my $h = $schema->storage->dbh->prepare($q);
417 my ($saved_image_id) = $h->fetchrow_array();
419 if ($saved_image_id) {
420 print STDERR Dumper
"Image $temp_file has already been added to the database and will not be added again.";
421 $image = SGN
::Image
->new( $schema->storage->dbh, $saved_image_id, $c );
422 $image_id = $image->get_image_id();
425 $image->set_sp_person_id($user_id);
426 my $ret = $image->process_image($temp_file, 'project', $project_id, $linking_table_type_id);
428 return {error
=> "Image processing for $temp_file did not work. Image not associated to stock_id $stock_id.<br/><br/>"};
430 print STDERR
"Saved $temp_file\n";
431 my $stock_associate = $image->associate_stock($stock_id);
432 $image_id = $image->get_image_id();
433 my $added_image_tag_id = $image->add_tag($image_tag);
435 $observationunit_stock_id_image_id{$stock_id} = $image_id;
438 print STDERR
"$img_name Not Included in the uploaded phenotype spreadsheet, skipping..\n";
441 return {return => \
%observationunit_stock_id_image_id};
444 sub upload_drone_imagery_zipfile
{
446 my $image_zip = shift;
448 my $project_id = shift;
449 my $c = $self->config();
450 my $schema = $c->dbic_schema("Bio::Chado::Schema");
451 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
452 my $dbh = $schema->storage->dbh;
454 my $archived_zip = CXGN
::ZipFile
->new(archived_zipfile_path
=>$image_zip);
455 my $file_members = $archived_zip->file_members();
457 return {error
=> 'Could not read your zipfile. Is it .zip format?</br></br>'};
460 my $linking_table_type_id = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'raw_drone_imagery', 'project_md_image')->cvterm_id();
461 print STDERR Dumper
scalar(@
$file_members);
463 foreach (@
$file_members) {
464 my $image = SGN
::Image
->new( $dbh, undef, $c );
465 #print STDERR Dumper $_;
466 my $temp_file = $image->upload_zipfile_images($_);
467 push @image_files, $temp_file;
469 return {image_files
=> \
@image_files};
472 sub upload_zipfile_images
{
474 my $file_member = shift;
476 my $filename = $file_member->fileName();
478 my $zipfile_image_temp_path = $self->config()->get_conf("basepath") . $self->config()->get_conf("tempfiles_subdir") . "/temp_images/photos";
479 make_path
($zipfile_image_temp_path);
481 $self->config()->get_conf("basepath")
482 . $self->config()->get_conf("tempfiles_subdir")
485 system("chmod 775 $zipfile_image_temp_path");
486 $file_member->extractToFileNamed($temp_file);
493 my $temp_file = shift;
494 my $upload_fh = shift;
496 ### 11/30/07 - change this so it removes existing file
498 # # only copy file if it doesn't already exist
500 if ( -e
$temp_file ) {
504 open UPLOADFILE
, '>', $temp_file or die "Could not write to $temp_file: $!\n";
507 while (<$upload_fh>) {
509 #warn "Read another chunk...\n";
513 warn "Done uploading.\n";
518 =head2 associate_stock
520 Usage: $image->associate_stock($stock_id);
521 Desc: associate a Bio::Chado::Schema::Result::Stock::Stock object with this image
522 Ret: a database id (stock_image_id)
529 sub associate_stock
{
531 my $stock_id = shift;
532 my $username = shift;
535 $username = $self->config->can('user_exists') ?
$self->config->user->get_object->get_username : $self->config->username;
538 my $metadata_schema = $self->config->dbic_schema('CXGN::Metadata::Schema');
539 my $metadata = CXGN
::Metadata
::Metadbdata
->new($metadata_schema, $username);
540 my $metadata_id = $metadata->store()->get_metadata_id();
542 my $q = "INSERT INTO phenome.stock_image (stock_id, image_id, metadata_id) VALUES (?,?,?) RETURNING stock_image_id";
543 my $sth = $self->get_dbh->prepare($q);
544 $sth->execute($stock_id, $self->get_image_id, $metadata_id);
545 my ($stock_image_id) = $sth->fetchrow_array;
546 return $stock_image_id;
549 die "No username. Could not save image-stock association!\n";
557 Usage: $image->remove_stock($stock_id);
558 Desc: remove an association to Bio::Chado::Schema::Result::Stock::Stock object with this image
559 Ret: a database id (stock_image_id)
568 my $stock_id = shift;
570 my $q = "DELETE FROM phenome.stock_image WHERE stock_id = ? AND image_id = ?";
571 my $sth = $self->get_dbh->prepare($q);
572 $sth->execute($stock_id, $self->get_image_id);
579 Usage: $image->get_stocks
580 Desc: find all stock objects linked with this image
581 Ret: a list of Bio::Chado::Schema::Result::Stock::Stock
588 my $schema = $self->config->dbic_schema('Bio::Chado::Schema' , 'sgn_chado');
590 my $q = "SELECT stock_id FROM phenome.stock_image WHERE image_id = ? ";
591 my $sth = $self->get_dbh->prepare($q);
592 $sth->execute($self->get_image_id);
593 while (my ($stock_id) = $sth->fetchrow_array) {
594 my $stock = $schema->resultset("Stock::Stock")->find( { stock_id
=> $stock_id } ) ;
595 push @stocks, $stock;
599 =head2 associate_individual
601 Usage: DEPRECATED, Individual table is not used any more . Please use stock instead
602 $image->associate_individual($individual_id)
603 Desc: associate a CXGN::Phenome::Individual with this image
604 Ret: a database id (individual_image)
611 sub associate_individual
{
613 my $individual_id = shift;
614 warn "DEPRECATED. Individual table is not used any more . Please use stock instead";
615 my $query = "INSERT INTO phenome.individual_image
616 (individual_id, image_id) VALUES (?, ?)";
617 my $sth = $self->get_dbh()->prepare($query);
618 $sth->execute($individual_id, $self->get_image_id());
620 my $id= $self->get_currval("phenome.individual_image_individual_image_id_seq");
625 =head2 get_individuals
627 Usage: DEPRECATED. Use the stock table .
628 $self->get_individuals()
629 Desc: find associated individuals with the image
630 Ret: list of 'Individual' objects
637 sub get_individuals
{
639 warn "DEPRECATED. Individual table is not used any more . Please use stock instead";
640 my $query = "SELECT individual_id FROM phenome.individual_image WHERE individual_image.image_id=?";
641 my $sth = $self->get_dbh()->prepare($query);
642 $sth->execute($self->get_image_id());
644 while (my ($individual_id) = $sth->fetchrow_array()) {
645 my $i = CXGN
::Phenome
::Individual
->new($self->get_dbh(), $individual_id);
646 if ( $i->get_individual_id() ) { push @individuals, $i; } #obsolete individuals should be ignored!
652 =head2 associate_experiment
654 Usage: $image->associate_experiment($experiment_id);
655 Desc: associate and image with and insitu experiment
663 sub associate_experiment
{
665 my $experiment_id = shift;
666 my $query = "INSERT INTO insitu.experiment_image
667 (image_id, experiment_id)
669 my $sth = $self->get_dbh()->prepare($query);
670 $sth->execute($self->get_image_id(), $experiment_id);
671 my $id= $self->get_currval("insitu.experiment_image_experiment_image_id_seq");
676 =head2 get_experiments
680 Ret: a list of CXGN::Insitu::Experiment objects associated
688 sub get_experiments
{
690 my $query = "SELECT experiment_id FROM insitu.experiment_image
692 my $sth = $self->get_dbh()->prepare($query);
693 $sth->execute($self->get_image_id());
694 my @experiments = ();
695 while (my ($experiment_id) = $sth->fetchrow_array()) {
696 push @experiments, CXGN
::Insitu
::Experiment
->new($self->get_dbh(), $experiment_id);
701 =head2 associate_project
703 Usage: $image->associate_project($project_id);
704 Desc: associate an image with an project entry via the phenome.project_md_image table
712 sub associate_project
{
714 my $project_id = shift;
715 my $linking_table_type_id = shift;
716 my $query = "INSERT INTO phenome.project_md_image
717 (image_id, project_id, type_id)
719 my $sth = $self->get_dbh()->prepare($query);
720 $sth->execute($self->get_image_id(), $project_id, $linking_table_type_id);
721 my $id= $self->get_currval("phenome.project_md_image_project_md_image_id_seq");
725 =head2 associate_fish_result
727 Usage: $image->associate_fish_result($fish_result_id)
728 Desc: associate a CXGN::Phenome::Individual with this image
736 sub associate_fish_result
{
738 my $fish_result_id = shift;
739 my $query = "INSERT INTO sgn.fish_result_image
740 (fish_result_id, image_id) VALUES (?, ?)";
741 my $sth = $self->get_dbh()->prepare($query);
742 $sth->execute($fish_result_id, $self->get_image_id());
743 my $id= $self->get_currval("sgn.fish_result_image_fish_result_image_id_seq");
747 =head2 get_fish_result_clone_ids
749 Usage: my @clone_ids = $image->get_fish_result_clones();
750 Desc: because fish results are associated with genomic
751 clones, this function returns the genomic clone ids
752 that are associated through the fish results to
753 this image. The clone ids can be used to construct
754 links to the BAC detail page.
755 Ret: A list of clone_ids
762 sub get_fish_result_clone_ids
{
764 my $query = "SELECT distinct(clone_id) FROM sgn.fish_result_image join sgn.fish_result using(fish_result_id) WHERE fish_result_image.image_id=?";
765 my $sth = $self->get_dbh()->prepare($query);
766 $sth->execute($self->get_image_id());
767 my @fish_result_clone_ids = ();
768 while (my ($fish_result_clone_id) = $sth->fetchrow_array()) {
769 push @fish_result_clone_ids, $fish_result_clone_id;
771 return @fish_result_clone_ids;
774 =head2 get_associated_objects
784 sub get_associated_objects
{
786 my @associations = ();
787 my @stocks=$self->get_stocks();
788 foreach my $stock (@stocks) {
789 my $stock_id = $stock->stock_id();
790 my $stock_name = $stock->name();
791 push @associations, [ "stock", $stock_id, $stock_name ];
794 foreach my $exp ($self->get_experiments()) {
795 my $experiment_id = $exp->get_experiment_id();
796 my $experiment_name = $exp->get_name();
798 push @associations, [ "experiment", $experiment_id, $experiment_name ];
800 #print "<a href=\"/insitu/detail/experiment.pl?experiment_id=$experiment_id&action=view\">".($exp->get_name())."</a>";
803 foreach my $fish_result_clone_id ($self->get_fish_result_clone_ids()) {
804 push @associations, [ "fished_clone", $fish_result_clone_id ];
806 foreach my $locus ($self->get_loci() ) {
807 push @associations, ["locus", $locus->get_locus_id(), $locus->get_locus_name];
809 foreach my $o ($self->get_organisms ) {
810 push @associations, ["organism", $o->organism_id, $o->species];
813 foreach my $cvterm ( $self->get_cvterms ) {
814 push @associations, ["cvterm" , $cvterm->cvterm_id, $cvterm->name];
816 return @associations;
819 =head2 associate_locus
821 Usage: $image->associate_locus($locus_id)
822 Desc: associate a locus with this image
830 sub associate_locus
{
832 my $locus_id = shift;
833 my $sp_person_id= $self->get_sp_person_id();
834 my $query = "INSERT INTO phenome.locus_image
839 my $sth = $self->get_dbh()->prepare($query);
843 $self->get_image_id()
846 my $locus_image_id= $self->get_currval("phenome.locus_image_locus_image_id_seq");
847 return $locus_image_id;
853 Usage: $self->get_loci
854 Desc: find the locus objects asociated with this image
855 Ret: a list of locus objects
864 my $query = "SELECT locus_id FROM phenome.locus_image WHERE locus_image.obsolete = 'f' and locus_image.image_id=?";
865 my $sth = $self->get_dbh()->prepare($query);
866 $sth->execute($self->get_image_id());
869 while (my ($locus_id) = $sth->fetchrow_array()) {
870 $locus = CXGN
::Phenome
::Locus
->new($self->get_dbh(), $locus_id);
877 =head2 associate_organism
879 Usage: $image->associate_organism($organism_id)
888 sub associate_organism
{
890 my $organism_id = shift;
891 my $sp_person_id= $self->get_sp_person_id();
892 my $query = "INSERT INTO metadata.md_image_organism
896 VALUES (?, ?, ?) RETURNING md_image_organism_id";
897 my $sth = $self->get_dbh()->prepare($query);
903 my ($image_organism_id) = $sth->fetchrow_array;
904 return $image_organism_id;
909 Usage: $self->get_organisms
910 Desc: find the organism objects asociated with this image
911 Ret: a list of BCS Organism objects
920 my $schema = $self->config->dbic_schema('Bio::Chado::Schema' , 'sgn_chado');
921 my $query = "SELECT organism_id FROM metadata.md_image_organism WHERE md_image_organism.obsolete != 't' and md_image_organism.image_id=?";
922 my $sth = $self->get_dbh()->prepare($query);
923 $sth->execute($self->get_image_id());
925 while (my ($o_id) = $sth->fetchrow_array ) {
926 push @organisms, $schema->resultset("Organism::Organism")->find(
927 { organism_id
=> $o_id } );
933 =head2 get_associated_object_links
939 Description: gets the associated objects as links in tabular format
943 sub get_associated_object_links
{
946 foreach my $assoc ($self->get_associated_objects()) {
948 if ($assoc->[0] eq "stock") {
949 $s .= "<a href=\"/stock/$assoc->[1]/view\">Stock name: $assoc->[2].</a>";
952 if ($assoc->[0] eq "experiment") {
953 $s .= "<a href=\"/insitu/detail/experiment.pl?experiment_id=$assoc->[1]&action=view\">insitu experiment $assoc->[2]</a>";
956 if ($assoc->[0] eq "fished_clone") {
957 $s .= qq { <a href
="/maps/physical/clone_info.pl?id=$assoc->[1]">FISHed clone id
:$assoc->[1]</a
> };
959 if ($assoc->[0] eq "locus" ) {
960 $s .= qq { <a href
="/phenome/locus_display.pl?locus_id=$assoc->[1]">Locus name
:$assoc->[2]</a
> };
962 if ($assoc->[0] eq "organism" ) {
963 $s .= qq { <a href
="/organism/$assoc->[1]/view/">Organism name
:$assoc->[2]</a
> };
965 if ($assoc->[0] eq "cvterm" ) {
966 $s .= qq { <a href
="/cvterm/$assoc->[1]/view/">Cvterm
: $assoc->[2]</a
> };
973 =head2 associate_cvterm
975 Usage: $image->associate_cvterm($cvterm_id)
976 Desc: link uploaded image with a cvterm
977 Ret: database ID md_image_cvterm_id
979 Side Effects: Insert database row
984 sub associate_cvterm
{
986 my $cvterm_id = shift;
987 my $sp_person_id= $self->get_sp_person_id();
988 my $query = "INSERT INTO metadata.md_image_cvterm
992 VALUES (?, ?, ?) RETURNING md_image_cvterm_id";
993 my $sth = $self->get_dbh()->prepare($query);
999 my ($image_cvterm_id) = $sth->fetchrow_array;
1000 return $image_cvterm_id;
1005 Usage: $self->get_cvterms
1006 Desc: find the cvterm objects asociated with this image
1007 Ret: a list of BCS Cvterm objects
1016 my $schema = $self->config->dbic_schema('Bio::Chado::Schema' , 'sgn_chado');
1017 my $query = "SELECT cvterm_id FROM metadata.md_image_cvterm WHERE md_image_cvterm.obsolete != 't' and md_image_cvterm.image_id=?";
1018 my $sth = $self->get_dbh()->prepare($query);
1019 $sth->execute( $self->get_image_id() );
1021 while (my ($cvterm_id) = $sth->fetchrow_array ) {
1022 push @cvterms, $schema->resultset("Cv::Cvterm")->find(
1023 { cvterm_id
=> $cvterm_id } );
1028 =head2 remove_associated_cvterm
1030 Usage: $self->remove_associated_cvterm($cvterm_id)
1031 Desc: removes the specified cvterm associated with this image
1039 sub remove_associated_cvterm
{
1042 my $cvterm_id = shift;
1043 my $query = "DELETE FROM metadata.md_image_cvterm
1044 WHERE cvterm_id=? and image_id=?";
1046 my $sth = $self->get_dbh()->prepare($query);
1049 $self->get_image_id,
1055 sub associate_phenotype
{
1058 my $image_hash = shift;
1060 # Copied from CXGN::Phenotypes:StorePhenotypes->save_archived_images_metadata because
1061 # the class required too many parameters to instantiate.
1062 my $query = "INSERT into phenome.nd_experiment_md_images (nd_experiment_id, image_id) VALUES (?, ?);";
1063 my $sth = $self->get_dbh()->prepare($query);
1065 while (my ($nd_experiment_id, $image_id) = each %$image_hash) {
1066 $sth->execute($nd_experiment_id, $image_id);
1072 sub remove_associated_phenotypes
{
1076 # Find the information for creating our association row
1077 my $query = "DELETE from phenome.nd_experiment_md_images where image_id = ?";
1079 my $sth = $self->get_dbh()->prepare($query);
1081 $self->get_image_id,