package SlewProcess;
use strict;
use English;
use Carp;
use vars qw(@ISA $VERSION $name $author $date $version @instList $numberOfStreams);
@ISA = qw(Module);
use ModuleResources;
use ModuleUtil;
# Declare identity, version, author, date, etc.
$name = __PACKAGE__;
$VERSION = '0.17';
$version = $VERSION;
$author = 'Duncan Law-Green, Richard Saxton,Pedro Rodriguez,Jose Vicente Perea';
$date = '2016-08-04';
#
# ChangeLog
# =========
#
# version 0.17 - 2016-08-04 (PR, JVP)
# ------------
#
# + FITS Slew step images produced also in PNG format
# + Source detection (eslewsearch) produces source lists per image band (bands: 6,7,8) and 1 merged source list per Slew
#
# version 0.16 - 2016-07-07 PR
# ------------
#
# + paste slew products tidy from Finalize module
#
# version 0.15 - 2010-08-10 DLG
# ------------
# + insert filter/mode check for slew processing
#
# version 0.14 - 2009-06-23 DLG
# ------------
# + changed instList to 'all' to correspond with MakeCIF
#
# version 0.13 - 2009-06-19 DLG
# ------------
# + numberOfStreams set to 1
#
# version 0.12 - 2009-06-19 DLG
# ------------
# + added shared vars to fix module crash
#
# version 0.11 - 2009-06-15 DLG
# ------------
# + continue coding, return success() added
#
# version 0.1 - 2009-03-18 DLG
# -----------
# + coding started
#
# About Slew Processing
# ---------------------
# SlewProcess calls the SAS wrapper task 'eslewchain'. eslewchain splits an EPIC slew
# into small sections, roughly one degree in length, and generates images and exposure
# maps for each section. It makes use of the tasks atthkgen, attcalc, evselect and
# eexpmap.
# Processing to proceed as follows:
#
# * Copy slew datafile (SDF) into a clean directory, and point at it with the environment
# variable SAS_ODF
#
# * Run ccfbuild and point to the CCF with SAS_CCF
#
# * Run odfingest
#
# * Run epproc in a working directory
#
# * Set SAS_ATTITUDE environment variable to 'RAF'
#
# * Run eslewchain in the directory containing the event file produced by epproc
# For guide to issues involved in interpreting slew images, see Saxton et al. 2008, A&A 480, 611
# Declare list of instruments this module is interested in
@instList = qw(all);
# Number of streams
sub numberOfStreams
{
return 1;
}
# Rules method
sub evaluateRules
{
# Ignore conditions
# Ignore if not doing slew processing
return ignore()
if ( ! $ENV{'PCMS_ISSLEW'} );
# Start conditions
start()
if complete(
module => 'MakeCIF'
, instrument => 'all'
, stream => 1
);
}
# Action method
sub performAction
{
info("Module version number: $version");
# Check for slew dataset here (how??), exit ignore() if not found
if ( ! $ENV{'PCMS_ISSLEW'} ) {
info("PCMS_ISSLEW is not set. Ignoring SlewProcess.");
return ignore();
}
info("PCMS_ISSLEW is set. Continuing with SlewProcess.");
# Work out exposure ID for PN, MOS1, MOS2
my $pn_exp_id = exposureID(instrument => 'epn',
stream => 1 );
my $mos1_exp_id = exposureID(instrument => 'emos1',
stream => 1 );
my $mos2_exp_id = exposureID(instrument => 'emos2',
stream => 1 );
# Fetch filter and mode, trip exception if not correct for slew processing
my $pn_filter = getExposureProperty(instrument => 'epn',
exp_id => $pn_exp_id,
name => 'filter') || "Inactive" ;
info("PN Filter: $pn_filter");
my $mos1_filter = getExposureProperty(instrument => 'emos1',
exp_id => $mos1_exp_id,
name => 'filter') || "Inactive" ;
info("MOS1 Filter: $mos1_filter");
my $mos2_filter = getExposureProperty(instrument => 'emos2',
exp_id => $mos2_exp_id,
name => 'filter') || "Inactive" ;
info("MOS2 Filter: $mos2_filter");
my $pn_mode = getExposureProperty(instrument => 'epn',
exp_id => $pn_exp_id,
name => 'mode') || "Inactive" ;
info("PN Mode: $pn_mode");
my $mos1_mode = getExposureProperty(instrument => 'emos1',
exp_id => $mos1_exp_id,
name => 'mode') || "Inactive" ;
info("MOS1 Mode: $mos1_mode");
my $mos2_mode = getExposureProperty(instrument => 'emos2',
exp_id => $mos2_exp_id,
name => 'mode') || "Inactive" ;
info("MOS2 Mode: $mos2_mode");
if ($pn_filter !~ /^Medium/ && $mos1_filter !~ /^Medium/ && $mos2_filter !~ /^Medium/) {
info("Incorrect EPIC filter for slew: $pn_filter | $mos1_filter | $mos2_filter, should be Medium.");
info("Ignoring SlewProcess...");
return ignore();
}
if ($pn_mode !~ /^(PrimeFullWindow|PrimeLargeWindow|PrimeFullWindowExtended)/ && $mos1_mode !~ /^(PrimeFullWindow|PrimeLargeWindow|PrimeFullWindowExtended)/ && $mos2_mode !~ /^(PrimeFullWindow|PrimeLargeWindow|PrimeFullWindowExtended)/) {
info("Incorrect EPIC mode for slew: $pn_mode | $mos1_mode | $mos2_mode, should be PrimeFullWindow || PrimeLargeWindow || PrimeFullWindowExtended.");
info("Ignoring SlewProcess...");
return ignore();
}
# Run epproc
#
info("Running epproc on slew sequence");
doCommand(
'epproc'
, removetemporaries => 1
, removeintermediategtis => 1
, removeintermediateeventlists => 1
, selectccds => 0
)
or return exception();
# Run eslewchain
# SAS task has no parameters in documentation
info("Running eslewchain on slew sequence");
doCommand(
'eslewchain'
, withpng => 'yes'
)
or return exception();
# Run eslewsearch
# SAS task has no parameters in documentation
info("Running eslewsearch on slew sequence");
doCommand(
'eslewsearch'
)
or return exception();
# Set up parameters for slew product tidy ----------------
# Modified for eslewchain-1.4, PCMS-"compliant" filenames
my $rootdir = $ModuleResources::Seqdb->{'directories'}{'root'};
info("Sequence root directory: $rootdir");
# move files to intermediate subdir
# Does the new eslewchain still create these?
# moveFile(source => 'histo.fits',
# destination => 'intermediate/histo.fits');
# moveFile(source => 'image.fits',
# destination => 'intermediate/image.fits');
# moveFile(source => 'spectrum.fits',
# destination => 'intermediate/spectrum.fits');
# moveFile(source => "temp_sp_*",
# destination => 'intermediate/');
moveFile(source => "*Badpixels.ds",
destination => 'intermediate/') unless ignored( module => 'SlewProcess', stream => 1 );
# Identify output products and assign PCMS-compatible filenames
# Attitude file:P*OBX000ATTTSR0000.FITS
my $obsid = $ENV{'SAS_RAND_SEED'};
my ($attfile) = glob("$rootdir/P*OBX000ATTTSR0000.ds");
my $attdest = newFile(class => 'product'
,instrument => 'ob'
,content => 'SLEW ATTITUDE FILE'
,format => 'FITS'
);
moveFile(source => "$attfile"
,destination => "$attdest") unless ignored( module => 'SlewProcess', stream => 1 );
my $sourcename = sprintf("P%010s",$obsid);
doCommand(
'addattribute', set => $attdest
, attributename => 'OBJECT'
, attributetype => 'string'
, stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
) unless ignored(module => 'SlewProcess', stream => 1 );
# Single raw events file: P*PNS003SLEVLI0000.FITS
my ($rawfile) = glob("$rootdir/*ImagingEvts.ds");
# my ($rawfile) = glob("$rootdir/P*PNS003PIEVLI0SLW.ds");
my $rawdest = newFile(class=>'product'
,instrument => 'epn'
,exp_id => 'S003'
,content => 'SLEW SINGLE RAW EVENT LIST'
,format => 'FITS'
);
moveFile(source => "$rawfile"
,destination => "$rawdest") unless ignored( module => 'SlewProcess', stream => 1 );
my $sourcename = sprintf("P%010s",$obsid);
doCommand(
'addattribute', set => $rawdest
, attributename => 'OBJECT'
, attributetype => 'string'
, stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
) unless ignored( module => 'SlewProcess', stream => 1 );
# filtered event files per step: P*PNS003PIEVLI0*.FITS
my $filtfile;
my $filtdest;
my $filtstep = 0;
my @filtlist = glob("$rootdir/P*PNS003PIEVLI0*.ds");
foreach $filtfile (@filtlist) {
$filtdest = newFile(class => 'product'
,instrument => 'epn'
,exp_id => 'S003'
,content => 'SLEW STEP FILTERED EVENT LIST'
,format => 'FITS'
,src_num => "$filtstep" # this needs to be in decimal, not hex
);
moveFile(source => "$filtfile"
,destination => "$filtdest");
my $sourcename = sprintf("P%010s_%03x",$obsid,$filtstep);
doCommand(
'addattribute', set => $filtdest
, attributename => 'OBJECT'
, attributetype => 'string'
, stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
);
$filtstep++;
}
# Slew step band exposure map: P*PNS003EXPMAPbiii.FITS
# Loop over slew bands
my $slewband;
my $stepfile;
my $stepdest;
foreach $slewband ( '6', '7', '8' ) {
$filtstep = 0;
my @steplist = glob("$rootdir/P*PNS003EXPMAP${slewband}*.ds");
foreach $stepfile (@steplist) {
my $stepdest = newFile(class => 'product'
, instrument => 'epn'
, exp_id => 'S003'
, content => 'SLEW STEP EXPOSURE MAP'
, format => 'FITS'
, src_num => "$filtstep"
, band => "$slewband"
);
moveFile(source => "$stepfile"
,destination=> "$stepdest");
my $sourcename = sprintf("P%010s_%03x",$obsid,$filtstep);
doCommand(
'addattribute', set => $stepdest
, attributename => 'OBJECT'
, attributetype => 'string'
, stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
);
$filtstep++;
}
}
# Slew step band images: P*PNS003IMAGE_biii.FITS
# Loop over slew bands
my $pngfile ;
my $pngdest ;
foreach $slewband ( "6", "7", "8" ) {
$filtstep = 0;
my @steplist = glob("$rootdir/P*PNS003IMAGE_${slewband}*.ds");
foreach $stepfile (@steplist) {
my $pngfile = $stepfile ;
$pngfile =~ s/ds/png/;
my $pngdest = newFile(class => 'product'
, instrument => 'epn'
, exp_id => 'S003'
, content => 'SLEW STEP IMAGE'
, format => 'PNG'
, src_num => "$filtstep"
, band => "$slewband"
);
moveFile(source => "$pngfile"
,destination=> "$pngdest");
my $stepdest = newFile(class => 'product'
, instrument => 'epn'
, exp_id => 'S003'
, content => 'SLEW STEP IMAGE'
, format => 'FITS'
, src_num => "$filtstep"
, band => "$slewband"
);
moveFile(source => "$stepfile"
,destination=> "$stepdest");
# Set OBJECT header to source step name (Nora's request)
my $sourcename = sprintf("P%010s_%03x",$obsid,$filtstep);
doCommand(
'addattribute', set => $stepdest
, attributename => 'OBJECT'
, attributetype => 'string'
, stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
);
$filtstep++;
}
}
# Slew band source lists: P*PNS003OMSRLIb000.FITS ( 1 source list per band )
# Loop over slew bands
#my $pngfile ;
#my $pngdest ;
foreach $slewband ( "6", "7", "8" ) {
#$filtstep = 0;
my ($stepfile) = glob("$rootdir/P*PNS003OMSRLI${slewband}*.FIT");
#foreach $stepfile (@steplist) {
#my $pngfile = $stepfile ;
#$pngfile =~ s/ds/png/;
#my $pngdest = newFile(class => 'product'
# , instrument => 'epn'
# , exp_id => 'S003'
# , content => 'SLEW STEP IMAGE'
# , format => 'PNG'
# , src_num => "$filtstep"
# , band => "$slewband"
# );
#
#moveFile(source => "$pngfile"
# ,destination=> "$pngdest");
my $stepdest = newFile(class => 'product'
, instrument => 'epn'
, exp_id => 'S003'
, content => 'EPIC OBSERVATION ML SOURCE LIST'
, format => 'FITS'
#, src_num => "$filtstep"
, band => "$slewband"
);
moveFile(source => "$stepfile"
,destination=> "$stepdest");
# Set OBJECT header to source step name (Nora's request)
#my $sourcename = sprintf("P%010s_%03x",$obsid,$filtstep);
#doCommand(
# 'addattribute', set => $stepdest
# , attributename => 'OBJECT'
# , attributetype => 'string'
# , stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
# );
#$filtstep++;
#}
}
# Merged source list: P*PNS003OMSSLI0000.FITS ( 1 source list per Slew )
my ($mergedSrcListTemp) = glob("$rootdir/P*PNS003OMSSLI0000.FIT");
my $mergedSrcList = newFile(class => 'product'
, instrument => 'epn'
, exp_id => 'S003'
, content => 'EPIC SUMMARY SOURCE LIST FOR SLEW DATA'
, format => 'FITS'
#, src_num => "$filtstep"
#, band => "$slewband"
);
## Write Extension name (SRCLIST) if it does not exist
#if (!hasFITSExtension(file => $mergedSrcListTemp, extension => "SRCLIST")){
# doCommand(
# 'addattribute', set => $mergedSrcListTemp
# , attributename => 'EXTNAME'
# , attributetype => 'string'
# , stringvalue => "SRCLIST"
# #, attributecomment => '"name of this binary table extension"'
# );
#}
moveFile(source => "$mergedSrcListTemp"
,destination=> "$mergedSrcList");
# Unfiltered step images: P*PNS003UNFDAT8*FITS
$filtstep = 0;
my $unffile;
my $unfdest;
my @unflist = glob("$rootdir/P*PNS003UNFDAT8*.ds");
foreach $unffile (@unflist) {
$unfdest = newFile(class => 'product'
,instrument => 'epn'
,exp_id => 'S003'
,content => 'UNFILTERED SLEW STEP IMAGE'
,format => 'FITS'
,src_num => "$filtstep" # this needs to be in decimal, not hex
,band => '8'
);
moveFile(source => "$unffile"
,destination => "$unfdest");
# Set OBJECT header to source step name (Nora's request)
my $sourcename = sprintf("P%010s_%03x",$obsid,$filtstep);
doCommand(
'addattribute', set => $unfdest
, attributename => 'OBJECT'
, attributetype => 'string'
, stringvalue => "$sourcename"
# , attributecomment => '"Object name"'
);
$filtstep++;
}
# Tidy: Drop all ds files from root directory
my @unlinklist = glob("$rootdir/*.ds");
unlink @unlinklist unless ignored( module => 'SlewProcess', stream => 1 );
# --------------------------------------------------------
# +++ StampKeywords +++
# Import portion of StampKeywords module to run here for slew
# Add basic headers to all FITS product files
info("Starting StampKeywords subroutine...");
my ( @name, @type, @value, @comment, @withcomment );
# Fetch list of product files
my @list = findFile(
class => 'product'
, 'format' => 'FITS'
);
# We really really really want to avoid running addattribute on ACDS products.
# This can happen if we restart a post ACDS sequence at a pre ACDs stage and apply --acds_magic=1
@list = grep { $_ !~ /CAX000/} @list;
return success() unless @list;
# Fetch observation properties
my $obs = getObservationProperties();
my $odsver = getOdsVer();
my $odfver = getOdfVer();
# Use any old file to get global properties (like seq id)
my $info = fileInfo( class => 'product', name => $list[0] );
# Set values of keywords
# Reset OBJECT keyword to 'Slew' for slew sequences
# push @name, 'OBJECT';
# push @type, 'string';
# push @value, 'Slew';
# push @comment, 'Object name';
# push @withcomment, 'y';
push @name, 'SEQ_ID';
push @type, 'string';
push @value, $info->{sequence};
push @comment, 'Pipeline sequence';
push @withcomment, 'y';
push @name, 'REVOLUT';
push @type, 'string';
push @value, $obs->{orbit};
push @comment, 'Satellite Revolution Number';
push @withcomment, 'y';
push @name, 'PROCDATE';
push @type, 'string';
push @value, $obs->{procdate};
push @comment, 'Processing date';
push @withcomment, 'y';
push @name, 'PROCREV';
push @type, 'string';
push @value, $obs->{procrevision};
push @comment, 'Processing revision';
push @withcomment, 'y';
push @name, 'PPSVERS';
push @type, 'string';
push @value, $obs->{ppsversion};
push @comment, 'PPS configuration';
push @withcomment, 'y';
push @name, 'SASVERS';
push @type, 'string';
push @value, $obs->{sasversion};
push @comment, 'SAS version';
push @withcomment, 'y';
push @name, 'ODSVER';
push @type, 'string';
push @value, "$odsver";
push @comment, 'ODS version';
push @withcomment, 'y';
push @name, 'ORIGIN';
push @type, 'string';
push @value, 'Leicester/SSC';
push @comment, 'Origin of FITS file';
push @withcomment, 'y';
# Added block to hack OBSERVER keyword name in slews - DLG
push @name, 'OBSERVER';
push @type, 'string';
push @value, 'XMM-Newton';
push @comment, 'Observer';
push @withcomment, 'y';
push @name, 'ODFVER';
push @type, 'string';
push @value, sprintf('%03d',$odfver);
push @comment, 'ODF_VERSION';
push @withcomment, 'y';
# CONTENT keyword must be last in the list, as we set its value in
# the loop
push @name, 'CONTENT';
push @type, 'string';
push @comment, 'Contents of file';
push @withcomment, 'y';
# Loop over each file
foreach my $file (@list)
{
next unless fileExists( file => $file );
my $l_info = fileInfo( class => 'product', name => $file );
# Set the other keywords
doCommand(
'addattribute', set => $file
, attributename => [@name]
, attributetype => [@type]
, stringvalue => [ @value, uc( $l_info->{content} ) ]
, attributecomment => [@comment]
)
or return exception();
}
info("StampKeywords subroutine complete!");
# --------------------------------------------------------
# Return success
success();
}
# need to rename output files by SSC band names
# get translation table?
1;