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;