package OMMosaic; use strict; use English; use Carp; use vars qw(@ISA $VERSION $name $author $date $version @instList $numberOfStreams); @ISA = qw(Module); use ModuleResources; # Declare identity, version, author, date, etc. $name = __PACKAGE__; $VERSION = '2.30'; $version = $VERSION; $author="Duncan John Fyfe, Duncan Law-Green, Eduardo Ojero, Ed Chapin"; $date="2013-06-11"; # # ChangeLog # ========= # # Version 2.30 - 2013-06-11 (EC) # ------------ # # + Merge changes from SOC version. # # Version 2.29 - 2012-06-15 (DLG) # ------------ # # + Add {Partial|Full} Frane Engineering Mode PFENG2, FFENG2 to list of OMMosaic modes # # Version 2.28 - 2012-05-02 (DLG) # # + Eliminate use of GIF bitmaps # # ------------ # # Version 2.27.1 - 2011-08-09 EOP # -------------- # # + Removed creation of GIF to avoid crashing on 64-bit. PNG file is created directly and GIF to PNG transformation is removed. # # Version 2.27 - 2009-05-01 (DLG) # # + explicitly set mincorr=0 per SRR's suggestion # # ------------ # # Version 2.26 - 2009-05-01 (DLG) # # - Remove exposure parameter (not required in SAS 9) # # ------------ # # Version 2.25 - 2005-09-13 (RGW) # # + shortened intermediate filenames # # ------------ # # Version 2.24 - 2004-01-14 (DJF) # ------------ # # + Updated evaluateRules. The module was not ignoring itself properly. # # Version 2.23 - 2003-12-10 (DJF) # ------------ # # + Adapted doCommand to use anonymous lists for list parameters # # Version 2.22 - 2002-12-13 (DJF) # ------------ # # + implot parameter changes. Merged plotfile/Device # # Version 2.21 - 2002-12-11 (DJF) # ------------ # # + Change implot parameter withsrclistset to withsrclisttab (SAS 5.4) # # Version 2.20 - 2002-03-11 (DJF) # ------------ # # + Amended to look for exposure from rudi-5 side windows if we are missing the central image. # # Version 2.19 - 2002-02-22 (DH) # ------------ # # + Minor bug fix. If statement had => instead of >= . # # Version 2.18 - 2002-02-20 (DFJ) # ------------ # # + Removed 100000 second limit in module. # # Version 2.17 - 2002-01-24 (DFJ) # ------------ # # + Fixed logic for totaling duration # + Added if/then to deal with exposure times outside of ommosaic task limits # # # Version 2.20 - 2002-03-11 (DJF) # ------------ # # + Amended to look for exposure from rudi-5 side windows if we are missing the central image. # # Version 2.19 - 2002-02-22 (DH) # ------------ # # + Minor bug fix. If statement had => instead of >= . # # Version 2.18 - 2002-02-20 (DFJ) # ------------ # # + Removed 100000 second limit in module. # # Version 2.17 - 2002-01-24 (DFJ) # ------------ # # + Fixed logic for totaling duration # + Added if/then to deal with exposure times outside of ommosaic task limits # # Version 2.20 - 2002-03-11 (DJF) # ------------ # # + Amended to look for exposure from rudi-5 side windows if we are missing the central image. # # Version 2.19 - 2002-02-22 (DH) # ------------ # # + Minor bug fix. If statement had => instead of >= . # # Version 2.18 - 2002-02-20 (DFJ) # ------------ # # + Removed 100000 second limit in module. # # Version 2.17 - 2002-01-24 (DFJ) # ------------ # # + Fixed logic for totaling duration # + Added if/then to deal with exposure times outside of ommosaic task limits # # Version 2.16 - 2002-01-23 (DFJ) # ------------ # # + Added determination of total exposure and passing of it to ommosaic task # # # Version 2.15 - 2001-12-17 (DFJ) # ------------ # # + Changed full frame sky image context strings to get around # problem with 'too long' intermedaite file names. # # Version 2.14 - 2001-12-04 (DFJ) # ------------ # # + Added word MOSAIC to prtoduct content strings # # Version 2.13 - 2001-12-03 (DFJ) # ------------ # # + Added condition to stop mosaicing of single ENG2 or ENG4 images # # Version 2.12 - 2001-11-29 (DFJ) # ------------ # # + Fixed and changed evaluate rules. There need be no dependance on OMFastAnalyse # # Version 2.11 - 2001-11-29 (DFJ) # ------------ # # + Corrected grouping of images. The end conditions meant the # last image got missed. # # Version 2.10 - 2001-11-28 (DFJ) # ------------ # # + Added creation of PNG images from mosaics # # Version 2.09 - 2001-11-28 (DFJ) # ------------ # # + Corrected osw to osw_id in product filename creation # # Version 2.08 - 2001-11-28 (DFJ) # ------------ # # + Removed debugging code. # + Fixed naming of mosaic products # + Removed some of the excessive log output # # Version 2.07 - 2001-11-28 (DFJ) # ------------ # # + added debugging code to help track a problem with the per filter processing # # Version 2.06 - 2001-11-28 (DFJ) # ------------ # # + Fixing per filter processing # # Version 2.05 - 2001-11-28 (DFJ) # ------------ # # + Fix grouping of images prior to mosaicing # # Version 2.04 - 2001-11-28 (DFJ) # ------------ # # + Correct reading of ASCII files containing image details # # Version 2.03 - 2001-11-27 (DFJ) # ------------ # # + Correct usage of readASCIIFile # # Version 2.02 - 2001-11-27 (DFJ) # ------------ # # + Fix evaluateRules dependence on OMImageAnalyse # # Version 2.01 - 2001-11-26 (DFJ) # ------------ # # + Added new product content strings # + Changes to accomodate output from OMImageAnalyse of a single ENG2 mode # # Version 2.00 - 2001-11-26 (DFJ) # ------------ # # + Major rearangement to accomodate per filter and per mode products. # This incorporates new rules for OM products devised enhance visibility # of products from different OM modes # + OMImageAnalyse now genererates ASCII lists containing Product file, mode and filter # information. These are used too define and control what mosaiced images are produced. # # Version 1.12 - 2001-11-07 (DFJ) # ------------ # # + Changed evaluaterules to ignore if all OMImgAnalyse and # OMFastAnalyse streams are ignored # # Version 1.11 - 2001-11-06 (DFJ) # ------------ # # + Change so module is flagged as ignored on failure of ommosaic task. # This is a temporary 'fix' to overcome a buggy ommosaic and allow # testing of the rest of the pipeline # # Version 1.10 - 2001-11-05 (DFJ) # ------------ # # + Changed to use skyimage which s what ommosaic requires. # # Version 1.09 - 2001-11-05 (DFJ) # ------------ # # + Added return exception for when ommosaic task fails. # # Version 1.08 - 2001-11-05 (DFJ) # ------------ # # + Fix selection of osw. Was failing to recognize 0 as a valid osw. # # Version 1.07 - 2001-11-02 (DJF) # ------------ # # + Change to logic. Generate up to three mosaiced images (Rudi5+EN2 , EN4 and FM) rather than # + one of three # # Version 1.06 - 2001-11-02 (DJF) # ------------ # # + Added test for imInfo{'osw'}. This was not the problem. # # Version 1.05 - 2001-11-01 (DJF) # ------------ # # + More log details. Still trying to find the source of a bug. # # Version 1.04 - 2001-11-01 (DJF) # ------------ # # + Removed check for imInfo{'osw'}. Looks like it isn't propperly null. # + Left in check for imgIngo('osw_id'}. Let's see if that works. # # Version 1.03 - 2001-11-01 (DJF) # ------------ # # + Output extra information to logs # # Version 1.02 - 2001-10-31 (DJF) # ------------ # # + Output extra information to logs # # Version 1.01 - 2001-10-31 (DJF) # ------------ # # + Change determination of osw to account for different sources (osw or osw_id) # # Version 1.00 - 2001-10-22 (DJF) # ------------ # # + Initial version # Declare list of instruments this module is interested in @instList=qw(om); # Number of streams sub numberOfStreams{ return 1; } sub evaluateRules { # Start conditions return ignore() if ignored(module => 'OMgetFlat' ,stream => 1 ); return ignore() if allIgnored(module=>'OMImageAnalyse' ,instrument => thisInstrument ); start() if allComplete(module => 'OMImageAnalyse' ,instrument => thisInstrument ); } sub performAction { info("Module version number: $version"); # OM modes are: USER , RUDI5_LR , RUDI5_HR , ENG2 , PFENG2, FFENG2, ENG4 and FAST # We do not Mosaic FAST images # Modes written by OMImageAnalyse my ($USER,$RUDI5_LR,$RUDI5_HR,$ENG2,$PFENG2,$FFENG2,$ENG4) = ('USER','RUDI5_LR','RUDI5_HR','ENG2','PFENG2','FFENG2','ENG4'); # Output Modes used by OMMosaic (we don't generate High Resoultion RUDI5 mosaics my $MosaicModes = [$USER,$RUDI5_LR,$ENG2,$PFENG2,$FFENG2,$ENG4]; info("Looking For Images to Mosaic..."); #Determine what Sky Images were written my @SkyImgDetailsFiles = findFile(class =>'intermediate' ,instrument => thisInstrument ,format => "ASCII" ,content => "OM SKY IMAGE DETAILS" ); unless (scalar(@SkyImgDetailsFiles)) { info("No Sky Images to mosaic."); return success(); } my @SkyImgDetails = (); foreach my $file (@SkyImgDetailsFiles) { my @details = readASCIIFile(name=>$file); next unless (scalar(@details)); foreach my $line (@details) { my @tmp = split("\\|",$line); push (@SkyImgDetails,\@tmp) if (scalar(@tmp)); } } my $count = scalar(@SkyImgDetails); unless ($count) { info("No Sky Images to mosaic."); return success(); } info("Found $count Images"); info ("Grouping Images by Mode then Filter"); # Sort details on: OM Mode, Filter # 0 = Filename , 1 = Img Mode , 2 = Filter ,3 duration, 4 exp_id my ($filename_p,$mode_p,$filter_p,$duration_p,$exp_id_p) = (0,1,2,3,4); my @SortedSkyImgDetails = sort { ${$a}[$mode_p] cmp ${$b}[$mode_p] || ${$a}[$filter_p] cmp ${$b}[$filter_p] || ${$a}[$filename_p] cmp ${$b}[$filename_p] } @SkyImgDetails; # separate into image groups on mode then filter my @ImgGroups = (); my $Img = shift (@SortedSkyImgDetails); while (defined($Img)) { my $oldmode = $$Img[$mode_p]; info("Mode: $oldmode"); my @mode_tmp=(); while ( (defined($Img)) && ($$Img[$mode_p] eq $oldmode) ) { my $oldfilter = $$Img[$filter_p]; info("Filter: $oldfilter"); my (@expids,@alt_expids); my ($duration,$alt_duration) = (0,0); my @filter_tmp = (); while ( (defined($Img)) && ($$Img[$filter_p] eq $oldfilter) && ($$Img[$mode_p] eq $oldmode) ) { info("Image File : $$Img[$filename_p]"); # Add up a total for the duration here. We only want duration from one window per exposure. # For RUDI5 we use the central image. We set the side images durations -ve in OMImageAnalyse # to allow us to test for it here. # For USER mopde we use the first duration from an exposure if ( ($$Img[$duration_p] > 0) && !(grep /$$Img[$exp_id_p]/,@expids) ) { push(@expids,$$Img[$exp_id_p]); $duration += $$Img[$duration_p]; } else { # This bit is in case we are missing the central image from a Rudi-5 set. # If that is the case we need to get the exposure time from one of the side images. # # The problem is image is defined across 4 exposures. The rudi5group # returns a new exposure id of th form Rn where n the the Rudi5 group. # The rudi5 groups are: # Group Exposure id's # 1 S401 - S404 # 2 S405 - S409 # etc my $r5g = &rudi5group($$Img[$exp_id_p]); if ( $r5g && !(grep /$r5g/,@expids) ) { $alt_duration += abs($$Img[$duration_p]); push(@expids,$r5g); } } # Building up lists of files for each filter within each mode push(@filter_tmp,$$Img[$filename_p]); $Img = shift (@SortedSkyImgDetails); } # use $alt_duration if we have duration = 0 and a rudi5 set. $duration = $alt_duration if (!$duration && $alt_duration); push (@mode_tmp,[$oldfilter,$duration,\@filter_tmp]) unless ( (scalar @filter_tmp < 2) && ($oldmode ne $RUDI5_LR) ); } push(@ImgGroups,[$oldmode,\@mode_tmp]); } &per_mode($MosaicModes,\@ImgGroups); return success(); } sub per_mode { my ($MosaicModes,$Groups) = @_; my ($USER,$RUDI5_LR,$ENG2,$PFENG2,$FFENG2,$ENG4) = @$MosaicModes; my %Content_Strings = ( $USER => "OM USER WINDOWS SKY IMAGE MOSAIC" ,$RUDI5_LR => "OM RUDI-5 SKY IMAGE MOSAIC" ,$ENG2 => "OM FULL-FRAME LORES SKY IMAGE MOSAIC" ,$PFENG2 => "OM PARTIAL-FRAME LORES SKY IMAGE MOSAIC" ,$FFENG2 => "OM FULL-FRAME LORES SKY IMAGE MOSAIC" ,$ENG4 => "OM FULL-FRAME HIRES SKY IMAGE MOSAIC" ); info("Creating Images..."); foreach my $group (@$Groups) { my ($mode,$filters) = @$group; info("MODE: $mode"); if ($mode eq $USER) { &per_filter($Content_Strings{"$USER"},$filters); } elsif ($mode eq $RUDI5_LR) { &per_filter($Content_Strings{"$RUDI5_LR"},$filters); } elsif ($mode eq $ENG2 || $mode eq $PFENG2 || $mode eq $FFENG2) { &per_filter($Content_Strings{"$ENG2"},$filters); } elsif ($mode eq $ENG4) { &per_filter($Content_Strings{"$ENG4"},$filters); } else { info("There are no rules for generating Mosaic products for this mode ($mode)."); info("No Mosaic products will be generated."); } info("Done: $mode"); } } sub per_filter { my ($content,$Filters) = @_; foreach my $f (@$Filters) { my ($filter,$duration,$imgs) = @$f; info("FILTER: $filter"); &mosaic($filter,$duration,$content,$imgs); } } sub mosaic{ my ($filter,$duration,$content,$Imgs) = @_; my $newImg=newFile(class=>'product' ,instrument => thisInstrument ,osw_id => "$filter" ,content => "$content" ); # Determine total exposure time = duration. info("CREATING: $newImg, Duration: $duration"); #These limits are imposed by the ommosaic task # They may change in future if ($duration >= 10) { doCommand('ommosaic' ,imagesets => [@$Imgs] ,mosaicedset => $newImg ,mincorr => 0 # ,exposure => $duration ## Removed in SAS9 ) or return exception(); # CREATE PNG FROM MOSAICS my $intcnt; ($intcnt=$content)=~s/\s+//g; my $gifFile=newFile(class => 'intermediate' ,instrument => thisInstrument ,osw_id => "$filter" ,content => "$intcnt" ,format => 'GIF' ); my $pngFile=newFile(class => 'product' ,instrument => thisInstrument ,osw_id => "$filter" ,content => "$content" ,format => 'PNG' ); doCommand('implot' ,set => $newImg ,device => "$pngFile/PNG" ,withsrclisttab => 'no' ) or return exception(); # # Convert to PNG format # GIFtoPNG(source => $gifFile # ,destination => $pngFile # ) or return exception(); } else { info("The exposure time ($duration s) is outside of bounds set by the ommosaic task."); info("No Image Mosaic will be generated."); } } sub rudi5group { my ($expid) = @_; my $group = 0; return 0 unless ($expid =~ /^S4/); $expid =~ s/\D//g; while ($expid > 0) { $expid -= 4; $group++; } return "R${group}"; } 1;