Download

package OMSourceCombine;
use strict;
use English;
use Carp;
use vars
  qw(@ISA $VERSION $name $author $date $version @instList $numberOfStreams);
@ISA = qw(Module);
use ModuleResources;
#### DEBUG
use Data::Dumper;
#### DEBUG

# Declare identity, version, author, date, etc.
$name    = __PACKAGE__;
$VERSION = '3.7';
$version = $VERSION;
$author  = 'Richard West,Duncan John Fyfe,Ian Stewart,Duncan Law-Green,Jose Vicente Perea, Pedro Rodriguez';
$date    = '2016-03-29';

#
# ChangeLog
# =========
#
# Version 3.7 - 2016-03-29 (JVP)
# -----------
#
# + Mosaic detections (detections from stacked images)
#   Final Combined Source List ('ommergelists') and Combined Region as final products:
#	'OM OBSERVATION SOURCE LIST'	now includes source detection from stacked images (mosaic)
#	'OM OBSERVATION SOURCE REGION'	new ds9 region product containing all detected sources 
#
# Version 3.6 - 2016-03-23 (PR, JVP)
# -----------
#
# + Mosaic detections (detections from stacked images)
#   Final Combined Source List ('ommergelists') and Combined Region already in place (as intermediate products).
#
# Version 3.5 - 2016-03-22 (PR, JVP)
# -----------
#
# + Mosaic detections (detections from stacked images)
#   Final Combined Source List ('ommergelists') pending.
#
# Version 3.4 - 2012-03-22 (DLG)
# -----------
#
# + change omsrclistcomb input from intermediate reference catalogue to product
#
# Version 3.3 - 2008-09-29 (DLG)
# -----------
# 
# Add support for {Partial|Full} Frame Engineering Mode 2: PFENG2, FFENG2
#
# Version 3.2 - 2008-09-19 (DLG)
# -----------
# 
# Modifications to track/fix missing OM image products in PCMS-8.1
#
# Version 3.1 - 2006-01-18 (DJF)
# ------------
#
# + Was looking for filter value /grism/i rather than /G|H/i to indicate grism data.  
#
# Version 3.0 - 2005-11-18 (IMS)
# ------------
#
# + Add explicit perl module headers.  Previously these were supplied
#   at compile time.  This will make debugging and extending the modules
#   through additional perl libraries easier.
#
# + Code layout made more uniform with perltidy
# + Standerdized date format (ccyy-mm-dd)
# + Standerdized author list to use comma separator
# + Make use of perl $VERSION magic.  Now $Version = version = ''
#
# + No longer generates the USNO extract. This job is taken over by module USNOExtract. Added 'start' dependency on this module.
#
# Version 2.12 - 2005-09-28 (RGW)
# ------------
#
# + exclude grism exposure source lists from merging operation
#
# Version 2.11 - 2005-09-26 (RGW)
# ------------
#
# + added fall-back on to an OSW sky image if no mosaic is available
#   (image is currently chosen randomly, should maybe be the "largest"?)
#
# Version 2.10 - 2005-09-15 (RGW)
# ------------
#
# + removed dependency on SrcMerge, this module now creates its own
#   USNO digest
#
# Version 2.09 - 2005-09-14 (RGW)
# ------------
#
# + updated trigger conditions to depend on SrcMerge
# + omsrclistcomb now uses the USNO digest as input
#
# Version 2.08 - 2004-03-27 (DFJ)
# ------------
#
# + omsrclistcomb was being called with a 'joined list' rather than a list reference
#
# Version 2.07 - 2003-12-10 (DFJ)
# ------------
# 
# + Adapted doCommand to use anonymous lists for list parameters.
#
# Version 2.06 - 2001-11-29 (DFJ)
# ------------
# 
# + fixed evaluate rules was refering to intrument.
# + Removed dependance on OMFastAnalyse
# 
# Version 2.05 - 2001-11-29 (DFJ)
# ------------
# 
# + Corrected grouping of images. The end conditions meant the 
#   last image got missed.
# 
# Version 2.04 - 2001-11-28 (DJF)
# ------------
#
# + Fix call to omsrclistcomb
#
# Version 2.03 - 2001-11-28 (DJF)
# ------------
#
# + Fix call to omsrclistcomb
#
# Version 2.02 - 2001-11-28 (DJF)
# ------------
#
# + Fix call to omsrclistcomb
#
# Version 2.01 - 2001-11-28 (DJF)
# ------------
#
# + Fix call to omsrclistcomb
#
# Version 2.00 - 2001-11-28 (DJF)
# ------------
#
# + Major rewrite to accomodate new OM product names
#
# Version 1.10 - 2001-10-30 (DJF)
# ------------
#
# + Further amended evaluateRules to account for OMFastAnalyse and OMImageAnalyse running in parallel.
#
# Version 1.09 - 2001-10-25 (DJF)
# ------------
#
# + Amened evaluateRules to account for new OMFastAnalyse module
#
# Version 1.08 - 2001-03-16 (DH)
# ------------
#
# + Print out version number in performAction() for
#   tracking purposes.
#
# Version 1.07 - 2001-03-08 (DH)
# ------------
#
# + Make combined source list a product file rather than
#   an intermediate file.
#
# Version 1.06 - 2001-01-10 (DH)
# ------------
#
# + Add OMgetFlat to start rule.
#
# Version 1.05 - 2001-01-10 (DH)
# ------------
#
# + Add ignore rule.
#
# Version 1.04 - 2000-11-30 (DH)
# ------------
#
# + First production version.
#

# Declare list of instruments this module is interested in
@instList=qw(om);

# Number of streams
sub numberOfStreams{ return 1; }

sub evaluateRules {

	# Start conditions
	ignore() if ignored(module => 'OMgetFlat'
		,stream => 1);

	ignore() if allIgnored(module=>'OMImageAnalyse'
		,instrument => thisInstrument
	);

	ignore() if ignored(module => 'OMMosaic');

##### Now that we don't have to make a usno extract, do we need OMImageAnalyse and OMMosaic?
    start()
      if allComplete(
        module => 'OMImageAnalyse'
        , instrument => thisInstrument
      )
      and complete(
        module => 'OMMosaic'
      )
      and complete(
        module => 'USNOExtract'
        , instrument => 'all'
        , stream => 1
     );

}

sub performAction {
	info("Module version number: $version");

	# OM modes are: USER , RUDI5_LR , RUDI5_HR , ENG2 , PFENG2, FFENG2, ENG4 and FAST
	# Modified to include PFENG2, FFENG2 - DLG

	# We do not Combine FAST images

	# Modes written by OMImageAnalyse
	my ($USER,$RUDI5_LR,$ENG2,$PFENG2,$FFENG2,$ENG4) = ('USER','RUDI5_LR','ENG2','PFENG2','FFENG2','ENG4');
	my @CombineModesMOS = ('USER','RUDI5_LR','ENG2','PFENG2','FFENG2','ENG4');

	# Output Modes used by OMSourceCombine (we don't generate High Resoultion RUDI5 mosaics
	# assume PFENG2, FFENG2 use same combine modes as ENG2
	my $CombineModes = [$USER,$RUDI5_LR,$ENG2,$PFENG2,$FFENG2,$ENG4];


	info("Looking For Source Lists to Combine...");
	#Determine what Sky Images were written
	my @SrcLstDetailsFiles = findFile(class =>'intermediate'
		,instrument => thisInstrument
		,format => "ASCII"
		,content => "OM SRC IMAGE DETAILS"
	);
	
	unless (scalar(@SrcLstDetailsFiles)) {
		info("No Source Lists Images to Combine.");	
		return success();
	}
	
	my @SrcLstDetails = ();
	foreach my $file (@SrcLstDetailsFiles) {
#### DEBUG
	    info("DEBUG: file: $file");
#### DEBUG
		my @details = readASCIIFile(name=>$file);
		next unless (scalar(@details));

		# Fetch exposure ID
		my $info=fileInfo(class => 'intermediate',
				  name => $file);
		my $expid=$$info{'exp_id'};
		my $filter=getExposureProperty(instrument => 'om',
					       exp_id => $expid,
					       name => 'filter');
		#my $mode=getExposureProperty(instrument => 'om',
		#				 exp_id => $expid,
		#				 name => 'mode'
		#);

		if ($filter =~ /grism/i)
		{
			info("Ignoring grism source list for exposure=$expid");
			next;
		}
		
		foreach my $line (@details) 
		{
			# Shouldn't really need this second test but as with all things OM belt and braces and superglue oft saves the day.
			$line =~ /([GH])$/;
			if ($1)
			{
				info("Ignoring grism source list for exposure=$expid");
				next;
			}
			
			my @tmp = split("\\|",$line);
#### DEBUG
			info("DEBUG: line $line");
			my $debugtmp = Dumper(\@tmp);
			info("DEBUG: split to tmp: $debugtmp");

#### DEBUG		
			push (@SrcLstDetails,\@tmp)
			    if (scalar(@tmp));
		}
	}

#### DEBUG
	my $debugsrclstdetails = Dumper(\@SrcLstDetails);
	info("DEBUG: SrcLstDetails: $debugsrclstdetails");
#### DEBUG

	my $count = scalar(@SrcLstDetails);
	unless ($count) {
		info("No source lists to combine.");	
		return success();
	}
	info("Found $count Lists");
	info ("Grouping Lists by Mode then Filter");

    my $usnoList = findFile(
			    class => 'product'
			    , instrument => 'all'
			    , content => 'Reference catalogue'
			    , format => 'FITS'
			    , required => 'true'
			    );

	# Sort details on: OM Mode, Filter	
	# 0 = Filename , 1 = Src Mode , 2 = Filter 

	my ($filename_p,$mode_p,$filter_p) = (0,1,2);
	my @SortedSrcLstDetails = sort { ${$a}[$mode_p] cmp ${$b}[$mode_p] 
		|| ${$a}[$filter_p] cmp ${$b}[$filter_p] 
		|| ${$a}[$filename_p] cmp ${$b}[$filename_p] 
	} @SrcLstDetails;

#### DEBUG
	my $debugsortedsrclstdetails = Dumper(\@SortedSrcLstDetails);
	info("DEBUG: SortedSrcLstDetails: $debugsortedsrclstdetails");
#### DEBUG

	# separate into image groups on mode then filter

	my @SrcGroups = ();
	my $Src = shift (@SortedSrcLstDetails);
	while ( defined($Src) ) {
		my $oldmode = $$Src[$mode_p];
		info("Mode: $oldmode");
		my @mode_tmp=();

#### DEBUG
		info("DEBUG: Src: $Src");
		info("DEBUG: mode_p: $mode_p");
#		my @tempsrc = $$Src; 
#		my $debugtempsrc = Dumper(\@tempsrc);
		info("DEBUG: SSrc[modep]: $$Src[$mode_p]");
		info("DEBUG: SSrc[filterp]: $$Src[$filter_p]");
#### DEBUG
		
		while ( (defined($Src)) && ($$Src[$mode_p] eq $oldmode) ) {

			my $oldfilter = $$Src[$filter_p];
			info("Filter: $oldfilter");
			my @filter_tmp = ();

			while ( (defined($Src)) && ($$Src[$filter_p] eq $oldfilter) && ($$Src[$mode_p] eq $oldmode) ) {
			
				info("Image File : $$Src[$filename_p]");
				push(@filter_tmp,$$Src[$filename_p]);
				$Src = shift (@SortedSrcLstDetails);

			}
			push (@mode_tmp,[$oldfilter,\@filter_tmp]);
		}
		push(@SrcGroups,[$oldmode,\@mode_tmp]);
	}

	&per_mode($CombineModes, $usnoList, \@SrcGroups);


###
####  Now try Mosaic detections
###
#

        my $listmosaicsourcelists = findFile(
         class=> 'intermediate'
	 , instrument => thisInstrument
	 , format => "ASCII"
         , content => "MOSAIC SOURCE LISTS"
	);
	unless ($listmosaicsourcelists){
	    info("No MOSAIC lists to combine");
	    return success();
	};
        info ("reading file $listmosaicsourcelists");
	my @mosaiclists = readASCIIFile(name=>$listmosaicsourcelists);
        unless (scalar(@mosaiclists)){
	    info("No MOSAIC lists to combine");
            return success();
        };

	my $content = "OM OBSERVATION SOURCE LIST MOSAIC";


        &combine($content, $usnoList ,\@mosaiclists);

	my $SrcListMosaic = findFile(
	     class=> "product"
	     , instrument => thisInstrument
             , content => "OM OBSERVATION SOURCE LIST MOSAIC"
        );
	my $SrcListWindow = findFile(
	     class=> "product"
	     , instrument => thisInstrument
             , content => "OM OBSERVATION SOURCE LIST"
        );


        # Final Combined Source List and Combined Region
        my $newSrcList = newFile(
         class => 'intermediate'
        ,instrument => thisInstrument
        ,content => "final merged list"
       );

       doCommand('ommergelists'
	       , srclist1 => $SrcListWindow
	       , srclist2 => $SrcListMosaic
	       , outset => $newSrcList
	       , tolerance => 2
		, maxrawrate => 5
       ) or return exception();


	# Overwrite $SrcListWindow 'OM OBSERVATION SOURCE LIST' with the Combined Source List
	info ("DEBUG Copy $newSrcList to $SrcListWindow");
	copyFile(source => "$newSrcList", destination => $SrcListWindow);	# Overwrite original


	my $newSrcRegion = newFile(
	 class => 'product'
	,instrument => thisInstrument
	,content => "OM OBSERVATION SOURCE REGION"
	,format => "ASCII"
        );


        # Create $newSrcRegion 'OM OBSERVATION SOURCE REGION' : Combined Region
	doCommand('omregion'
	       , set =>  $newSrcList
	       , srcnumber  => 1
	       , srcradius => 3
	       , nfwhm => 3
		, bkginner => 1.2
		, bkgouter => 1.8
		, srcfile => $newSrcRegion
       ) or return exception();


	return success();
}

sub per_mode {
	my ($CombineModes, $usnoList, $Groups) = @_;
	my ($USER,$RUDI5_LR,$ENG2,$PFENG2,$FFENG2,$ENG4) = @$CombineModes;
	my $content = "OM OBSERVATION SOURCE LIST";

	info("Creating Combined Lists...");	

	###
	### Current Rules	###
	### Combine all OSW source lists except RUDI5_HR and OMFastAnalyse
	###	This code knows nothing of OMFastAnalyse source lists so we don't need to worry about it.
	### We need to discard all RUDI5_HR mode lines and combine the others into a single list
	###

	my @tobecombined = ();
	foreach my $group (@$Groups) {
		my ($mode,$filters) = @$group;
		info("MODE: $mode");
		if ($mode eq $USER) {
			push(@tobecombined,@{&per_filter($filters)});
		}
		elsif ($mode eq $RUDI5_LR) {
			push(@tobecombined,@{&per_filter($filters)});
		}
		elsif ($mode eq $ENG2) {
			push(@tobecombined,@{&per_filter($filters)});
		}
		elsif ($mode eq $PFENG2) {
			push(@tobecombined,@{&per_filter($filters)});
		}
		elsif ($mode eq $FFENG2) {
			push(@tobecombined,@{&per_filter($filters)});
		}
		elsif ($mode eq $ENG4) {
			push(@tobecombined,@{&per_filter($filters)});
		}
		else {
			info("There are no rules for generating a combined source list for this mode ($mode).");
			info("No product will be generated.");
		}
		info("Done: $mode");
	
	}

	&combine($content, $usnoList, \@tobecombined);
}

sub per_filter {
	my ($Filters) = @_;

	my @list = ();
	foreach my $f (@$Filters) {
		my ($filter,$lists) = @$f;
		info("FILTER: $filter");
		push(@list,@$lists);	
	}
	return \@list;
}

sub combine {
	my ($content, $usnoList, $SrcLists) = @_;
	
	my $newSrcList=newFile(class=>'product'
		,instrument => thisInstrument
		,content => "$content"
	);

	info("CREATING: $newSrcList");

	doCommand('omsrclistcomb'
		,sourcelistsets => $SrcLists
		,outset => $newSrcList
		, usecat => 'Y'
		, catfile => $usnoList
	) or return exception();

}
1;