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:
43 use File
::Temp qw
/ tempfile tempdir /;
44 use File
::Copy qw
/ copy move /;
45 use File
::Basename qw
/ basename /;
47 use CXGN
::DB
::Connection
;
50 use CatalystX
::GlobalContext
'$c';
52 use base qw
| CXGN
::Image
|;
56 Usage: my $image = SGN::Image->new($dbh)
59 Args: a database handle, optional identifier
60 Side Effects: an empty object is returned.
61 a database connection is established.
67 my ( $class, $dbh, $image_id, $context ) = @_;
70 my $self = $class->SUPER::new
(
71 dbh
=> $dbh || $context->dbc->dbh,
72 image_id
=> $image_id,
73 image_dir
=> $context->get_conf('static_datasets_path')."/".$context->get_conf('image_dir'),
76 $self->config( $context );
85 Usage: $self->get_image_url($size)
86 Desc: get the url for the image with a given size
87 Ret: a url for the image
88 Args: size (large, medium, small, thumbnail, original)
98 if( $self->config->test_mode && ! -e
$self->get_filename($size) ) {
99 # for performance, only try to stat the file if running in
100 # test mode. doing lots of file stats over NFS can actually be
102 return '/img/image_temporarily_unavailable.png';
105 my $url = join '/', (
107 $self->config()->get_conf('static_datasets_url'),
108 $self->config()->get_conf('image_dir'),
109 $self->get_filename($size, 'partial'),
117 Usage: $image->process_image($filename, "stock", 234);
118 Desc: creates the image and associates it to the type and type_id
120 Args: filename, type (experiment, stock, fish, locus, organism) , type_id
121 Side Effects: Calls the relevant $image->associate_$type function
128 my ($filename, $type, $type_id) = @_;
130 $self->SUPER::process_image
($filename);
132 if ( $type eq "experiment" ) {
133 #print STDERR "Associating experiment $type_id...\n";
134 $self->associate_experiment($type_id);
136 elsif ( $type eq "stock" ) {
137 #print STDERR "Associating stock $type_id...\n";
138 $self->associate_stock($type_id);
140 elsif ( $type eq "fish" ) {
141 #print STDERR "Associating to fish experiment $type_id\n";
142 $self->associate_fish_result($type_id);
144 elsif ( $type eq "locus" ) {
145 #print STDERR "Associating to locus $type_id\n";
146 $self->associate_locus($type_id);
148 elsif ( $type eq "organism" ) {
149 $self->associate_organism($type_id);
151 elsif ( $type eq "test") {
152 # need to return something to make this function happy
157 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";
162 =head2 config, context, _app
164 Get the Catalyst context object we are running with.
169 my ($self,$obj) = @_;
171 $self->{configuration_object
} = $obj if $obj;
173 return $self->{configuration_object
};
178 =head2 get_img_src_tag
183 Args: "large" | "medium" | "small" | "thumbnail" | "original" | "tiny"
190 sub get_img_src_tag
{
193 my $url = $self->get_image_url($size);
194 my $name = $self->get_name();
195 if ( $size && $size eq "original" ) {
197 my $static = $self->config()->get_conf("static_datasets_url");
202 . "\"><img src=\"$static/images/download_icon.png\" border=\"0\" alt=\""
206 elsif ( $size && $size eq "tiny" ) {
210 . "\" width=\"20\" height=\"15\" border=\"0\" alt=\""
218 . "\" border=\"0\" alt=\""
224 =head2 get_temp_filename
235 sub get_temp_filename
{
237 return $self->{temp_filename
};
241 =head2 set_temp_filename
252 sub set_temp_filename
{
254 $self->{temp_filename
} = shift;
257 =head2 apache_upload_image
261 Usage: my $temp_file_name = $image->apache_upload_image($apache_upload_object);
263 Ret: the name of the intermediate tempfile that can be
264 used to access down the road.
265 Args: an apache upload object
266 Side Effects: generates an intermediate temp file from an apache request
267 that can be handled more easily. Adds the remote IP addr to the
268 filename so that different uploaders don\'t clobber but
269 allows only one upload per remote addr at a time.
270 Errors: change 11/30/07 - removes temp file if already exists
271 # returns -1 if the intermediate temp file already exists.
272 # this probably means that the submission button was hit twice
273 # and that an upload is already in progress.
278 sub apache_upload_image
{
281 ### deanx jan 03 2007
282 # Adjust File name if using Windows IE - it sends whole paht; drive letter, path, and filename
284 if ( $ENV{HTTP_USER_AGENT
} =~ /msie/i ) {
285 my ( $directory, $filename ) = $upload->filename =~ m/(.*\\)(.*)$/;
286 $upload_filename = $filename;
289 $upload_filename = $upload->filename;
293 $self->config()->get_conf("basepath") . "/"
294 . $self->config()->get_conf("tempfiles_subdir")
296 . $ENV{REMOTE_ADDR
} . "-"
299 my $upload_fh = $upload->fh;
301 ### 11/30/07 - change this so it removes existing file
303 # # only copy file if it doesn't already exist
305 if ( -e
$temp_file ) {
309 open UPLOADFILE
, '>', $temp_file or die "Could not write to $temp_file: $!\n";
312 while (<$upload_fh>) {
314 #warn "Read another chunk...\n";
318 warn "Done uploading.\n";
324 =head2 associate_stock
326 Usage: $image->associate_stock($stock_id);
327 Desc: associate a Bio::Chado::Schema::Result::Stock::Stock object with this image
328 Ret: a database id (stock_image_id)
335 sub associate_stock
{
337 my $stock_id = shift;
339 my $user = $self->config->user_exists;
341 my $metadata_schema = $self->config->dbic_schema('CXGN::Metadata::Schema');
342 my $metadata = CXGN
::Metadata
::Metadbdata
->new($metadata_schema, $self->config->user->get_object->get_username);
343 my $metadata_id = $metadata->store()->get_metadata_id();
345 my $q = "INSERT INTO phenome.stock_image (stock_id, image_id, metadata_id) VALUES (?,?,?) RETURNING stock_image_id";
346 my $sth = $self->get_dbh->prepare($q);
347 $sth->execute($stock_id, $self->get_image_id, $metadata_id);
348 my ($stock_image_id) = $sth->fetchrow_array;
349 return $stock_image_id;
357 Usage: $image->get_stocks
358 Desc: find all stock objects linked with this image
359 Ret: a list of Bio::Chado::Schema::Result::Stock::Stock
366 my $schema = $self->config->dbic_schema('Bio::Chado::Schema' , 'sgn_chado');
368 my $q = "SELECT stock_id FROM phenome.stock_image WHERE image_id = ? ";
369 my $sth = $self->get_dbh->prepare($q);
370 $sth->execute($self->get_image_id);
371 while (my ($stock_id) = $sth->fetchrow_array) {
372 my $stock = $schema->resultset("Stock::Stock")->find( { stock_id
=> $stock_id } ) ;
373 push @stocks, $stock;
377 =head2 associate_individual
379 Usage: DEPRECATED, Individual table is not used any more . Please use stock instead
380 $image->associate_individual($individual_id)
381 Desc: associate a CXGN::Phenome::Individual with this image
382 Ret: a database id (individual_image)
389 sub associate_individual
{
391 my $individual_id = shift;
392 warn "DEPRECATED. Individual table is not used any more . Please use stock instead";
393 my $query = "INSERT INTO phenome.individual_image
394 (individual_id, image_id) VALUES (?, ?)";
395 my $sth = $self->get_dbh()->prepare($query);
396 $sth->execute($individual_id, $self->get_image_id());
398 my $id= $self->get_currval("phenome.individual_image_individual_image_id_seq");
403 =head2 get_individuals
405 Usage: DEPRECATED. Use the stock table .
406 $self->get_individuals()
407 Desc: find associated individuals with the image
408 Ret: list of 'Individual' objects
415 sub get_individuals
{
417 warn "DEPRECATED. Individual table is not used any more . Please use stock instead";
418 my $query = "SELECT individual_id FROM phenome.individual_image WHERE individual_image.image_id=?";
419 my $sth = $self->get_dbh()->prepare($query);
420 $sth->execute($self->get_image_id());
422 while (my ($individual_id) = $sth->fetchrow_array()) {
423 my $i = CXGN
::Phenome
::Individual
->new($self->get_dbh(), $individual_id);
424 if ( $i->get_individual_id() ) { push @individuals, $i; } #obsolete individuals should be ignored!
430 =head2 associate_experiment
432 Usage: $image->associate_experiment($experiment_id);
433 Desc: associate and image with and insitu experiment
441 sub associate_experiment
{
443 my $experiment_id = shift;
444 my $query = "INSERT INTO insitu.experiment_image
445 (image_id, experiment_id)
447 my $sth = $self->get_dbh()->prepare($query);
448 $sth->execute($self->get_image_id(), $experiment_id);
449 my $id= $self->get_currval("insitu.experiment_image_experiment_image_id_seq");
454 =head2 get_experiments
458 Ret: a list of CXGN::Insitu::Experiment objects associated
466 sub get_experiments
{
468 my $query = "SELECT experiment_id FROM insitu.experiment_image
470 my $sth = $self->get_dbh()->prepare($query);
471 $sth->execute($self->get_image_id());
472 my @experiments = ();
473 while (my ($experiment_id) = $sth->fetchrow_array()) {
474 push @experiments, CXGN
::Insitu
::Experiment
->new($self->get_dbh(), $experiment_id);
479 =head2 associate_fish_result
481 Usage: $image->associate_fish_result($fish_result_id)
482 Desc: associate a CXGN::Phenome::Individual with this image
490 sub associate_fish_result
{
492 my $fish_result_id = shift;
493 my $query = "INSERT INTO sgn.fish_result_image
494 (fish_result_id, image_id) VALUES (?, ?)";
495 my $sth = $self->get_dbh()->prepare($query);
496 $sth->execute($fish_result_id, $self->get_image_id());
497 my $id= $self->get_currval("sgn.fish_result_image_fish_result_image_id_seq");
501 =head2 get_fish_result_clone_ids
503 Usage: my @clone_ids = $image->get_fish_result_clones();
504 Desc: because fish results are associated with genomic
505 clones, this function returns the genomic clone ids
506 that are associated through the fish results to
507 this image. The clone ids can be used to construct
508 links to the BAC detail page.
509 Ret: A list of clone_ids
516 sub get_fish_result_clone_ids
{
518 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=?";
519 my $sth = $self->get_dbh()->prepare($query);
520 $sth->execute($self->get_image_id());
521 my @fish_result_clone_ids = ();
522 while (my ($fish_result_clone_id) = $sth->fetchrow_array()) {
523 push @fish_result_clone_ids, $fish_result_clone_id;
525 return @fish_result_clone_ids;
528 =head2 get_associated_objects
538 sub get_associated_objects
{
540 my @associations = ();
541 my @stocks=$self->get_stocks();
542 foreach my $stock (@stocks) {
543 my $stock_id = $stock->stock_id();
544 my $stock_name = $stock->name();
545 push @associations, [ "stock", $stock_id, $stock_name ];
548 foreach my $exp ($self->get_experiments()) {
549 my $experiment_id = $exp->get_experiment_id();
550 my $experiment_name = $exp->get_name();
552 push @associations, [ "experiment", $experiment_id, $experiment_name ];
554 #print "<a href=\"/insitu/detail/experiment.pl?experiment_id=$experiment_id&action=view\">".($exp->get_name())."</a>";
557 foreach my $fish_result_clone_id ($self->get_fish_result_clone_ids()) {
558 push @associations, [ "fished_clone", $fish_result_clone_id ];
560 foreach my $locus ($self->get_loci() ) {
561 push @associations, ["locus", $locus->get_locus_id(), $locus->get_locus_name];
563 foreach my $o ($self->get_organisms ) {
564 push @associations, ["organism", $o->organism_id, $o->species];
566 return @associations;
569 =head2 associate_locus
571 Usage: $image->associate_locus($locus_id)
572 Desc: associate a locus with this image
580 sub associate_locus
{
582 my $locus_id = shift;
583 my $sp_person_id= $self->get_sp_person_id();
584 my $query = "INSERT INTO phenome.locus_image
589 my $sth = $self->get_dbh()->prepare($query);
593 $self->get_image_id()
596 my $locus_image_id= $self->get_currval("phenome.locus_image_locus_image_id_seq");
597 return $locus_image_id;
603 Usage: $self->get_loci
604 Desc: find the locus objects asociated with this image
605 Ret: a list of locus objects
614 my $query = "SELECT locus_id FROM phenome.locus_image WHERE locus_image.obsolete = 'f' and locus_image.image_id=?";
615 my $sth = $self->get_dbh()->prepare($query);
616 $sth->execute($self->get_image_id());
619 while (my ($locus_id) = $sth->fetchrow_array()) {
620 $locus = CXGN
::Phenome
::Locus
->new($self->get_dbh(), $locus_id);
627 =head2 associate_organism
629 Usage: $image->associate_organism($organism_id)
638 sub associate_organism
{
640 my $organism_id = shift;
641 my $sp_person_id= $self->get_sp_person_id();
642 my $query = "INSERT INTO metadata.md_image_organism
646 VALUES (?, ?, ?) RETURNING md_image_organism_id";
647 my $sth = $self->get_dbh()->prepare($query);
653 my ($image_organism_id) = $sth->fetchrow_array;
654 return $image_organism_id;
659 Usage: $self->get_organisms
660 Desc: find the organism objects asociated with this image
661 Ret: a list of BCS Organism objects
670 my $schema = $self->config->dbic_schema('Bio::Chado::Schema' , 'sgn_chado');
671 my $query = "SELECT organism_id FROM metadata.md_image_organism WHERE md_image_organism.obsolete != 't' and md_image_organism.image_id=?";
672 my $sth = $self->get_dbh()->prepare($query);
673 $sth->execute($self->get_image_id());
675 while (my ($o_id) = $sth->fetchrow_array ) {
676 push @organisms, $schema->resultset("Organism::Organism")->find(
677 { organism_id
=> $o_id } );
683 =head2 get_associated_object_links
689 Description: gets the associated objects as links in tabular format
693 sub get_associated_object_links
{
696 foreach my $assoc ($self->get_associated_objects()) {
698 if ($assoc->[0] eq "stock") {
699 $s .= "<a href=\"/stock/$assoc->[1]/view\">Stock name: $assoc->[2].</a>";
702 if ($assoc->[0] eq "experiment") {
703 $s .= "<a href=\"/insitu/detail/experiment.pl?experiment_id=$assoc->[1]&action=view\">insitu experiment $assoc->[2]</a>";
706 if ($assoc->[0] eq "fished_clone") {
707 $s .= qq { <a href
="/maps/physical/clone_info.pl?id=$assoc->[1]">FISHed clone id
:$assoc->[1]</a
> };
709 if ($assoc->[0] eq "locus" ) {
710 $s .= qq { <a href
="/phenome/locus_display.pl?locus_id=$assoc->[1]">Locus name
:$assoc->[2]</a
> };
712 if ($assoc->[0] eq "organism" ) {
713 $s .= qq { <a href
="/organism/$assoc->[1]/view/">Organism name
:$assoc->[2]</a
> };