Download

package MakeMOSImage;
use strict;
use English;
use Carp;
use vars
  qw(@ISA $VERSION $name $author $date $version @instList $numberOfStreams);
@ISA = qw(Module);
use ModuleResources;
use ModuleUtil;
use Astro::FITS::CFITSIO qw(TRUE FALSE);

# Declare identity, version, author, date, etc.
$name    = __PACKAGE__;
$VERSION = '2.19';
$version = $VERSION;
$author  = 'Richard West,Dean Hinshaw,Duncan John Fyfe,Ian Stewart,Duncan Law-Green,Eduardo Ojero, Ed Chapin, Jose Vicente Perea';
$date    = '2015-11-16';

#
# ChangeLog
# =========
#
# Version 2.19 - 2015-11-16 (PR, JVP)
# ------------
#
# + Find sources to drop and add ($SFBLCRegionFileDrop,DETX,DETY) to region if it exists
#
# Version 2.18 - 2014-10-16 (JVP)
# ------------
#
# + Ignore module if no impaging mode is performed
#
# Version 2.17 - 2014-01-21 (EC)
# ------------
#
# + comment-out etruecolor calls (PPS SCR #7166)
#
# Version 2.16 - 2014-01-18 (EC)
# ------------
#
# + Rules altered to handle EPICImageSize
#
# Version 2.15 - 2013-06-11 (EC)
# ------------
#
# + Merge changes from SOC version.
#
# version 2.14 - 2012-05-03 DLG
# ------------
#
# + Modify examineGTI to use optimised GTI where found
#
# version 2.13 - 2012-05-03 DLG
# ------------
#
# + Eliminate use of GIF bitmaps
#
# version 2.12 - 2012-03-08 DLG
# ------------
#
# + Generate band-8 non-vig exposure map
#
# version 2.11 - 2012-02-29 DLG
# ------------
#
# + Generate band 8 image event list
#
# version 2.10 - 2011-06-30 DLG
# ------------
#
# + Add call to etruecolor to generate 3-band colour images 
#
# version 2.09.1 - 2011-08-09 EOP
# --------------
#	
# + Replace GIF by PNG to avoid crash on 64-bit.
# 
# version 2.09 - 2006-09-20
# ------------
#
# + Record EXPOSURE of band 8 image and state of flarescreening in the database.
#
# version 2.08 - 2006-01-20 DJF
# ------------
#
# + Moved isEmageEmpty code to common module library ModuleUtil.
#
# version 2.07 - 2005-11-22 IMS
# ------------
# + Oops, was making the gif of exposure map band 8 (new in version 2.04) but neglected to carry on and make the png.
#
# version 2.06 - 2005-11-16 IMS
# ------------
# + Incorporated DJF's shortened intermediate file names.
#
# version 2.05 - 2005-11-02 DJF
# ------------
# + Only pass band 1-5 pimin + pimax to non-vig exp amp eepmap call.
#   it fails if you pass it too many pimin and not enough images
#
# version 2.04 - 2005-11-02 IMS
# ------------
#
# + Shortened the content string (thus the name) of the non-vig exposure map.
# + Non-vig exp maps now only made for bands 1-5 (no longer for 8).
# + FOV intermediate image is no longer made as there does not seem to be a use for it.
# + Now makes band 8 exposure map PNG product.
#
# version 2.03 - 2005-09-23 IMS
# ------------
#
# + In the subroutine examineGTI, the reference $flareScreen rather than its value ${$flareScreen} was being tested. This resulted in (for example) event-filtering by empty flare GTI files. This is now fixed (I hope).
#
# version 2.02 - 2005-08-15 RGW
# ------------
#
# + reinstated filtered image event list
# + module was choosing not to create PNGs even though the full-band
#   image contained events
#
# version 2.01 - 2005-06-06 IMS
# ------------
#
# + FLAG selection #XMMEA_EM replaced by explicit '(FLAG & 0x766ba000)==0'. At present they are the same, but XMMEA_EM is subject to change, and it seems to me better to retain control of this area.
# + Band 8 flag selection now identical to other bands, except OUT_OF_FOV bit not tested.
# + Test for empty band!=8 image now done in same way as for band 8
#   (ie, uses fimgstat call within subroutine isImageEmpty). The
#   additional filtered image event list is then not necessary and is
#   no longer made.
# + Non-vignetted exposure map is now also made (as an intermediate file). This is to accommodate new esplinemap call in module ExpDetect-2.01.
#
# version 2.00 - 2005-05-09 DJF
# ------------
#
# + 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 = ''
##
# Version 1.11 - 06Apr2004 (DJF)
# ------------
#
# + Fixed exposure map creation.  Were creating for bands 1,2,3,5,6,8
#   rather than 1,2,3,4,5,8
#
# Version 1.10 - 29March2004 (DJF)
# ------------
#
# + Added fix for bad order return of search results from database.
#
# Version 1.09 - 29March2004 (DJF)
# ------------
#
# + Moved exposure map file 'creation' to afterempty image tests.
#   Otherwise we get spurious entries in ppssumm
#
# Version 1.08 - 03March2004 (DJF)
# ------------
#
# + Oops, one too few $ in dereference of $flareGTI
#
# Version 1.07 - 03March2004 (DJF)
# ------------
#
# + Dereference $flareGTI to get filename in expression.
#
#
# Version 1.06 - 03March2004 (DJF)
# ------------
#
# + Re-added omitted flare screening GTI filter expression.
#
# Version 1.05 - 03March2004 (DJF)
# ------------
#
# + Changed from using energyBands to new energyband(band,bound) function
#   in ModuleResources.
#
# Version 1.04 - 02March2004 (DJF)
# ------------
#
# + Removed superfluous addattribute of BKGDSCRN to band8fov image.
# + Correction to energy band selection.  Was returning index, low value
#   rather than low,high value
#
# Version 1.03 - 18Feb2004 (DJF)
# ------------
#
# + Addition of BKGDSCRN attribute to some images.  Had been lost during re-arrangement.
#
# Version 1.02 - 12Feb2004 (DJF)
# ------------
#
# + Use new PCMS function gtiTimeThreshold() to return threshold
#
# Version 1.01 - 14Jan2004 (DJF)
# ------------
#
# + Small Flare GTI filtering moved to MOSEvents module.  We need only
#   check the availability and ONTIME here.
#
# Version 1.00 - 2003-09-05 (DJF)
#
# + Forked MakeImage v1.63 into MakeMOSImage and MakePNImage.  This should
#   simplify the module, make it more readable and easier to see what selection
#   expressions are used for a given instrument and band.
# + Removed pn specific conditions
# + Cosmetic changes to make code more readable
# + Reordered per band processing to remove unnecessary band 8 tests
# + Sort on bands to ensure they are always processed in the same order.
# + Added extra info() lines to log reason for exit
# + Moved flare screening test into a subroutine
# + Moved empty image test into a subroutine
#
# MakeImage ChangeLog
#
# Version 1.63 - 2003-09-05 (DJF)
# ------------
#
# + Add test for image (max-min) > 1 to overcome bug in implot where image
#   has too small a range of values.
#
# Version 1.62 - 2003-06-30 (DJF)
# ------------
#
# + Give fimgstat all of its parameters
#
# Version 1.61 - 2003-06-30 (DJF)
# ------------
#
# + Add mode parameter to fimgstat.
#
# Version 1.60 - 2003-06-27 (DJF)
# ------------
#
# + Use ftool fimgstat to determine if images are
#   empty or not before calling implot.
#
# Version 1.59 - 2003-06-25 (DJF)
# ------------
#
# + Added PATTERN<=12 selection for MOS images across all bands
#
# Version 1.58 - 2002-12-13 (DJF)
# ------------
#
# + Only take copy of un-filtered flare GTI if it exists
#
# Version 1.57 - 2002-12-13 (DJF)
# ------------
#
# + implot parameter changes.  Merged plotfile/Device
#
# Version 1.56 - 2002-12-11 (DJF)
# ------------
#
# + Change implot parameter withsrclistset to withsrclisttab (SAS 5.4)
#
# Version 1.55 - 2002-11-04 (DJF)
# ------------
#
# + Remove PNG plot of flare background timeseries
#
# Version 1.54 - 2002-11-01 (DJF)
# ------------
#
# + returned OUT_OF_FOV filter to band 8 fov images
#
# Version 1.53 - 2002-10-18 (DJF)
# ------------
#
# Changed copy of pre-flare screened event list to use newFile not findFile
#
# Version 1.52 - 2002-10-18 (DJF)
# ------------
#
# fix parameters for flare background plot GIFtoPNG call
#
# Version 1.51 - 2002-10-18 (DJF)
# ------------
#
# change fplot yparm from COUNT to COUNTS.
#
# Version 1.50 - 2002-10-18 (DJF)
# ------------
#
# Test for flare background content was looking for cwrong extension name.
# changed to 'RATE'
#
# Version 1.49 - 2002-09-16 (DJF)
# ------------
#
# + Added plot of flare background timeseries product.
# + Test whether short GTI removal leaves an empty GTI table.
#   do not apply flare screening if this occurs.
# + readjusted flags.
#
# Version 1.48 - 2002-09-16 (DJF)
# ------------
#
# + Replaced missing pn event selection flags
#
# Version 1.47 - 2002-09-16 (DJF)
# ------------
#
# + Fixed pn band 8 image name.  Added axtra comments for debugging.
#
# Version 1.46 - 2002-07-23 (DJF)
# ------------
#
# + Fixed unmatched parentheses in selection expression
#
# Version 1.45 - 2002-07-19 (DJF)
# ------------
#
# + More debugging
#
# Version 1.44 - 2002-07-19 (DJF)
# ------------
#
# + More debugging
#
# Version 1.43 - 2002-07-19 (DJF)
# ------------
#
# + More debugging
#
# Version 1.42 - 2002-07-11 (DJF)
# ------------
#
# + Added debugging statements
#
# Version 1.41 - 2002-07-05 (DJF)
# ------------
#
# + Removed debugging statement
#
# Version 1.40 - 2002-07-05 (DJF)
# ------------
#
# + Changed pn selection flags to use #XMMEA_EP + OUT_OF_FOV
# + Rearanged code to make it easier to read
#
# Version 1.39 - 2002-07-01 (DJF)
# ------------
#
# + Added #XMMEA_EM filtering to EMOS Band 1-5 images
#
# Version 1.38 - 2002-06-10 (DJF)
# ------------
#
# + Shorten name of intermediate image event lists to
#	accomodate a bug in esplinemap.
#
# Version 1.37 - 2002-04-26 (DH)
# ------------
#
# + CLOSE_TO_ONBOARD_BAD flag changed to what it should be, ie.
#	CLOSE_TO_ONBOARD_BADPIX.
#
# Version 1.36 - 2002-04-09 (DH)
# ------------
#
# + Move the test on empty images, so that eexpmap does not
#	get run when images are empty.
#
# Version 1.35 - 2002-03-28 (DH)
# ------------
#
# + The BKGDSCRN keyword was not getting written to all images
#	in all cases.
#
# Version 1.34 - 2002-03-15 (DH)
# ------------
#
# + Apply attitude GTI to event lists when making images.
#
# Version 1.38 - 2002-06-10 (DJF)
# ------------
#
# + Shorten name of intermediate image event lists to
#	accomodate a bug in esplinemap.
#
# Version 1.37 - 2002-04-26 (DH)
# ------------
#
# + CLOSE_TO_ONBOARD_BAD flag changed to what it should be, ie.
#	CLOSE_TO_ONBOARD_BADPIX.
#
# Version 1.36 - 2002-04-09 (DH)
# ------------
#
# + Move the test on empty images, so that eexpmap does not
#	get run when images are empty.
#
# Version 1.35 - 2002-03-28 (DH)
# ------------
#
# + The BKGDSCRN keyword was not getting written to all images
#	in all cases.
#
# Version 1.34 - 2002-03-15 (DH)
# ------------
#
# + Apply attitude GTI to event lists when making images.
# Version 1.38 - 2002-06-10 (DJF)
# ------------
#
# + Shorten name of intermediate image event lists to
#	accomodate a bug in esplinemap.
#
# Version 1.37 - 2002-04-26 (DH)
# ------------
#
# + CLOSE_TO_ONBOARD_BAD flag changed to what it should be, ie.
#	CLOSE_TO_ONBOARD_BADPIX.
#
# Version 1.36 - 2002-04-09 (DH)
# ------------
#
# + Move the test on empty images, so that eexpmap does not
#	get run when images are empty.
#
# Version 1.35 - 2002-03-28 (DH)
# ------------
#
# + The BKGDSCRN keyword was not getting written to all images
#	in all cases.
#
# Version 1.34 - 2002-03-15 (DH)
# ------------
#
# + Apply attitude GTI to event lists when making images.
#
# Version 1.33 - 2002-03-15 (DH)
# ------------
#
# + Add CLOSE_TO_CCD_WINDOW and CLOSE_TO_ONBOARD_BAD to list of
#	exluded pn flags.
#
# Version 1.32 - 2002-03-12 (DH)
# ------------
#
# + BKGDSCRN keyword now always written (either T or F).  Comment
#	fixed.
#
# Version 1.31 - 2002-03-06 (DH)
# ------------
#
# + For now, set the OUT_OF_FOV flag for pn using the explicit value
#	of 0x10000, due to a bug in epevents.
#
# Version 1.30 - 2002-03-01 (DH)
# ------------
#
# + Fix bug which application of flags to pn fov image.
#
# Version 1.29 - 2002-02-25 (DH)
# ------------
#
# + Don't apply the FLAG filter if the flag mask is zero when making
#	the image for mosaicing.
# + Fix bug in evselect call for filtering out flare GTIs of less than
#	100 seconds.
#
# Version 1.28 - 2002-02-08 (DH)
# ------------
#
# + New method for specifying bitmask filters for event lists, in order
#	to make it more clear which flags are being used.
# + Remove GTIs from the flare screening GTI list which have a duration of
#	less than 100 seconds.
# + Add keyword BKGDSCRN to images where flare GTI was applied.
#
# Version 1.27 - 2001-11-07 (DH)
# ------------
#
# + Change the way that the selection criteria in 1.26 are implemented.  Now
#	test on the band number, and apply the selection only to the appropriate
#	bands.  Makes for a cleaner data subspace.
#
# Version 1.26 - 2001-11-06 (DH)
# ------------
#
# + Add selection criteria for PN images, which deselects ON_OFFSET_COLUMN for
#	PI less than 500:(PI>=500 || (PI<500 && FLAG & 0x8 == 0))
#
# Version 1.25 - 2001-11-05 (DH)
# ------------
#
# + Check for the creation of empty images, and if there are any, return ignore.
#
# Version 1.24 - 2001-10-31 (DH)
# ------------
#
# + Gti time threshold cut now gotten from pcms configuration
#	parameter GtiTimeThreshold.
#
# Version 1.23 - 2001-10-25 (DJF)
# ------------
#
# + Fix test on flag expression to allow hex characters ie \d => [\da-fA-F]
#
# Version 1.22 - 2001-10-22 (DJF)
# ------------
#
# + Set badclean=0 for eexpmap on MOS.  Suggested by JB.
#
#
# Version 1.21 - 2001-10-02 (DH)
# ------------
#
# + Combine FLAG filters and combine PI filters so as to produce
#	a more compact data subspace in the image products.
# + Get total flare GTI time by reading the new ONTIME keyword.
#
# Version 1.20 - 2001-10-01 (DH)
# ------------
#
# + New pattern and flag cuts for pn images, PATTERN<=12 and
#	FLAG < 131072.
# + Change energy band cut expression from PI<$pihi to PI<=$pihi.
#
# Version 1.19 - 2001-08-21 (DJF)
# ------------
#
# + Set flarescreening GTI threshold to 1000s
#
# Version 1.18 - 2001-08-16 (DJF)
# ------------
#
# + Re-enable minimum good time cut off for testing purposes.
#
# Version 1.17 - 2001-07-05 (DJF)
# ------------
#
# + Clean up after flare screen GTI minimum good time cut off testing
#
#
# Version 1.16 - 2001-07-05 (DJF)
# ------------
#
# + Testing Added flare screen GTI minimum good time cut off
#
# Version 1.15 - 2001-07-05 (DJF)
# ------------
#
# + Added flare screen GTI minimum good time cut off
#
# Version 1.14 - 2001-07-03 (DJF)
# ------------
#
# + Corrected new version date above
#
# Version 1.13 - 2001-07-02 (DJF)
# ------------
#
# + Added Generate log message when flare screening GTI not used.
#
# Version 1.12 - 2001-07-02 (DJF)
# ------------
#
# + Added test for empty flareGTI extension.
#
# Version 1.11 - 2001-06-07 (DH)
# ------------
#
# + Set ignore flag if imaging event list is empty.
#
# Version 1.10 - 2001-05-22 (DH)
# ------------
#
# + Combine all filter flags into one filter expression, so that
#	the DataSubspace in evselect does not run into a problem with
#	too many filters of too may components.
#
# Version 1.09 - 2001-05-21 (DH)
# ------------
#
# + Exclude CLOSE_TO_CCD_WINDOW events from pn images.
#
# Version 1.08 - 2001-05-03 (DH)
# ------------
#
# + Energy band ranges now stored as pipeline parameters, #	gotten via call to new energyBands() function.
# + Exclude out of FOV events from pn images used in emosaic.
#
# Version 1.07 - 2001-04-17 (DH)
# ------------
#
# + Fix problem introduced in 1.06, which was causing evselect
#	to not write data subspace information.
#
# Version 1.06 - 2001-04-17 (DH)
# ------------
#
# + Exclude ON_OFFSET_COLUMN events from pn images.
#
# Version 1.05 - 2001-03-30 (DH)
# ------------
#
# + Change value of eexpmap parameter 'attrebin' from 60 to 2.
#
# Version 1.04 - 2001-03-16 (DH)
# ------------
#
# + Print out version number in performAction() for
#	tracking purposes.
#
# Version 1.03 - 2001-01-31 (DH)
# ------------
#
# + Make special band 8 images for use in emosaic (ImageMerge module).
#
# Version 1.01 - 2000-11-30 (DH)
# ------------
#
# + First production version.
#
my %Flags = (
    'emos1' => {
        'default' => '(FLAG & 0x766ba000)==0'
        , '8'     => '(FLAG & 0x766aa000)==0'
        , '8fov'  => '(FLAG & 0x766ba000)==0'
      }
    , 'emos2' => {
        'default' => '(FLAG & 0x766ba000)==0'
        , '8'     => '(FLAG & 0x766aa000)==0'
        , '8fov'  => '(FLAG & 0x766ba000)==0'
    }
);

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

# Number of streams
sub numberOfStreams
{
    return numberOfExposures();
}

# Rules method
sub evaluateRules
{

    # Ignore conditions
    return ignore() if allIgnored( module => 'EPICImageSize' );

    # Start conditions
    start() if allComplete( module => 'EPICImageSize' );
}

# Action method
sub performAction
{
    info("Module version number: $version");
    my ( @ebandlo, @ebandhi );
    my @expr = ("(PATTERN<=12)");

    # Find exposure ID
    my $exp_id = exposureID(
        instrument => thisInstrument
        , stream => thisStream
    );
    my $content = "EPIC MOS imaging mode event list";

    # Find imaging event file for this exposure
    my $evFile = findFile(
        class => 'product'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , content => $content
    );
    if ( !$evFile )
    {
        # info("No imaging mode event list available for this instrument."
	info("No imaging mode event list available for this instrument. Ignoring further processing."
        );
        # return success();
	return ignore();
    }

    # Test the event list contains something usable.
    if ( numberFITSRows( file => $evFile, extension => 'EVENTS' ) == 0 )
    {
        info(
"Event list is empty, ignore the rest of the processing for this exposure."
        );
        return ignore();
    }

    # Find spacecraft attitude file
    my $attFile = findFile(
        class => 'product'
        , instrument => 'all'
        , content => 'Attitude time series'
        , required => 'true'
    );

    # Find attitude GTI
    my $attGTIFile = findFile(
        class => 'intermediate'
        , instrument => 'all'
        , content => 'Attitude GTI'
    );

    # Attach attitude GTI, if it exists
    push( @expr, "GTI($attGTIFile, TIME)" ) if $attGTIFile;

    # Find sources to drop
    my $sso_object = $ENV{PCMS_SSO_OBJECT};
    
    if ( $sso_object ){
    my $SFBLCRegionFileDrop = findFile(
        class => 'intermediate'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , content => 'SFBLC reg drop'
        , band => 8
        , format => 'FITS'
    );

    # Attach attitude GTI, if it exists
    push( @expr, "region($SFBLCRegionFileDrop,DETX,DETY)" ) if $SFBLCRegionFileDrop;
    }
    
    # Find flare GTI
    my $flareGTI;
    my $flareScreen = 0;

    # Examine GTIs to decide if flare screening should be applied.
    # add to the selection expression if so.
    &examineGTI( $exp_id, \$flareGTI, \$flareScreen, \@expr );

# Loop through each energy band, creating the image, test if the image is empty
    my $empty_image = 0;
    my $imFile;
    foreach my $band ( 1, 2, 3, 4, 5, 8 )
    {
        info("Band: $band");
        my ( $pilo, $pihi, @locexpr, @options, $filteredList );

        # Figure out PI limits for this energy band
        $pilo = energyBand( $band, 0 );
        $pihi = energyBand( $band, 1 );
        push( @ebandlo, $pilo );
        push( @ebandhi, $pihi );
        push( @locexpr, "(PI in ($pilo:$pihi])" );
        my $whichband = exists( $Flags{ thisInstrument() }{"$band"} )
          ? $band
          : 'default';
        if ( $Flags{ thisInstrument() }{"$whichband"} )
        {
            push( @locexpr, $Flags{ thisInstrument() }{"$whichband"} );
        }
        map { info("expr = $_"); } @expr;
        map { info("locexpr = $_"); } @locexpr;

        # Create raw photon image
        my $imgFile = newFile(
            class => 'product'
            , instrument => thisInstrument
            , exp_id => $exp_id
            , band => $band
            , content => 'EPIC image'
        );
        if ( $band == 8 )
        {

            # Keep a record of the filename for use with eexpmap later
            $imFile = $imgFile;

            $filteredList = newFile(
                class => 'intermediate'
                , instrument => thisInstrument
                , exp_id => $exp_id
                , band => $band
                , content => 'image event list'
            );

            doCommand(
		      'evselect', table => "${evFile}:EVENTS"
		      , imageset => $imgFile
		      , xcolumn => 'X'
		      , ycolumn => 'Y'
		      , withimageset => 'Y'
		      , imagebinning => 'binSize'
		      , ximagebinsize => 80
		      , yimagebinsize => 80
#                , squarepixels => 'true'
		      , expression => join( ' && ', ( @expr, @locexpr ) )
		      , imagedatatype => 'Int32'
		      , withimagedatatype => 'true'
		      , writedss => 'true'
		      , updateexposure => 'true'
		      , keepfilteroutput => 'true'
		      , withfilteredset => 'true'
		      , filteredset => $filteredList
              )
              or return exception();

			# Record the band 8 EXPOSURE value in the database
			my @opt = ( file => $imgFile , extension => 'PRIMARY' , keyword => 'EXPOSURE' ) ;
			if ( hasFITSKeyword( @opt ) )
			{
				my $exposure =  readFITSKeyword( @opt );
				setExposureProperty( instrument => thisInstrument , exp_id => $exp_id , name => 'exposure' , value => $exposure );
			}


			my $imgStat = newFile(
				class => 'intermediate'
				, instrument => thisInstrument
				, exp_id => $exp_id
				, format => "ASCII"
				, band => $band
				, content => "Filtered image statistics"
			);
            if ( ! &ModuleUtil::isImageEmpty( $imgFile , $imgStat ) )
            {
                &band8fov(
                    $exp_id, $band, $imgFile, $evFile
                    , join(
                        '  && '
                        , (
                            @expr, @locexpr
                            , $Flags{ thisInstrument() }{'8fov'}
                        )
                      )
                    , $flareScreen
                );
            } else {
                $empty_image = 1;
                info("Image $imgFile is empty.");
			}
        }
        else
        {
            $filteredList = newFile(
                class => 'intermediate'
                , instrument => thisInstrument
                , exp_id => $exp_id
                , band => $band
                , content => 'image event list'
            );
            doCommand(
                'evselect', table => "${evFile}:EVENTS"
                , imageset => $imgFile
                , xcolumn => 'X'
                , ycolumn => 'Y'
                , withimageset => 'Y'
                , imagebinning => 'binSize'
                , ximagebinsize => 80
                , yimagebinsize => 80
#                , squarepixels => 'true'
                , expression => join( ' && ', ( @expr, @locexpr ) )
                , imagedatatype => 'Int32'
                , withimagedatatype => 'true'
                , writedss => 'true'
                , updateexposure => 'true'
                , keepfilteroutput => 'Y'
#                , keepfilteroutput => 'no'
                , withfilteredset => 'Y'
                , filteredset => $filteredList
              )
              or return exception();

            # Test filtered list for emptyness
#            if (
#                ( defined $filteredList )
#                && numberFITSRows(
#                    file => $filteredList
#                    , extension => 'EVENTS'
#                ) == 0
#              )
#            {
#                $empty_image = 1;
#                info("Filtered set $filteredList is empty.");
#            }
			my $imgStat = newFile(
				class => 'intermediate'
				, instrument => thisInstrument
				, exp_id => $exp_id
				, format => "ASCII"
				, band => $band
				, content => "Filtered image statistics"
			);
            if ( &ModuleUtil::isImageEmpty( $imgFile , $imgStat ) )
            {
                $empty_image = 1;
                info("Image $imgFile is empty.");
            }

        } # end if $band == 8

        doCommand(
            'addattribute', set => "${imgFile}:PRIMARY"
            , attributename => 'BKGDSCRN'
            , attributetype => 'boolean'
            , booleanvalue => $flareScreen ? 'T' : 'F'
            , attributecomment =>
              "\"\\\"Was background screening of the eventlist applied?\\\"\""
          )
          or return exception();
    }    #foreach band

# Stop processing this exposure (ie. don't do source detection) if
# there were any empty images 
    if ($empty_image)
    {
        info('Ignoring further processing due to empty images.');
        return ignore();
    }

    # create exposure map files
    my (@expmap, @nonVigExpMap);
    foreach my $b ( 1, 2, 3, 4, 5, 8 )
    {

        # Add to list of exposure maps
        my $expFile = newFile(
            class => 'product'
            , instrument => thisInstrument
            , exp_id => $exp_id
            , band => $b
            , content => 'EPIC exposure map'
        );
        push( @expmap, $expFile );

        #next if ($b eq '8'); # only need nonvigs for bands 1-5.

        # Add to list of exposure maps
        my $nonVigExpFile = newFile(
            class => 'intermediate'
            , instrument => thisInstrument
            , exp_id => $exp_id
            , band => $b
            , content => 'non-vig exposure map'
        );
        push( @nonVigExpMap, $nonVigExpFile );
    }

    # Run exposure map task to generate all exposure maps in parallel
    # We do this outside the above loop so the empty image tests
    # can have effect.
    if ( fileExists( file => $imFile ) )
    {
        doCommand(
            'eexpmap', imageset => $imFile
            , eventset => $evFile
            , attitudeset => $attFile
            , attrebin => 2
            , expimageset => [@expmap]
            , pimin => [@ebandlo]
            , pimax => [@ebandhi]
            , withvignetting => 'yes'
          )
          or return exception();

        doCommand(
            'eexpmap', imageset => $imFile
            , eventset => $evFile
            , attitudeset => $attFile
            , attrebin => 2
            , expimageset => [@nonVigExpMap]
            , pimin => [@ebandlo]
            , pimax => [@ebandhi]
            , withvignetting => 'no'
          )
          or return exception();
    }

    my $expFile = findFile(
        class => 'product'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , band => 8
        , content => 'EPIC exposure map'
    );

    return success() if (!$expFile);

    my $gifFile = newFile(
        class => 'intermediate'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , band => 8
        , content => 'exposure map'
        , format => 'GIF'
    );
    my $pngFile = newFile(
        class => 'product'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , band => 8
        , content => 'EPIC exposure map'
        , format => 'PNG'
    );
    doCommand(
        'implot', set => $expFile
        , device => "$pngFile/PNG"
        , withsrclisttab => 'no'
      )
      or return exception();
#    GIFtoPNG(
#        source => $gifFile
#        , destination => $pngFile
#      )
#      or return exception();

    return success();
}

sub examineGTI
{
    my ( $exp_id, $flareGTI, $flareScreen, $expr ) = @_;

    my $standardFlareGTI = findFile(
				    class => 'intermediate'
				    , instrument => thisInstrument
				    , exp_id => $exp_id
				    , content => 'flare GTI'
				    );

    my $optFlareGTI = findFile(
			       class => 'intermediate'
			       , instrument => thisInstrument
			       , exp_id => $exp_id
			       , content => 'Optimised flare GTI'
			       );

    if ( fileExists( file => $optFlareGTI) ) {
	${$flareGTI} = $optFlareGTI;
    } else {
	${$flareGTI} = $standardFlareGTI;
    }

    ${$flareScreen} = 0;
    if ( fileExists( file => ${$flareGTI} ) )
    {

        # Filter GTI, do we have ONTIME > total threshold ?
        if (
            numberFITSRows(
                file => ${$flareGTI}
                , extension => 'STDGTI'
            ) > 0
          )
        {

            # GTI time intervals
            # Setting $GTI_time_threshold = 0 will turn off GTI cut off
            my $GTI_time           = 0;
            my $GTI_time_threshold = gtiTimeThreshold();
            info(
"GTI total time interval threshold is $GTI_time_threshold."
            );
            if ($GTI_time_threshold)
            {
                $GTI_time = readFITSKeyword(
                    file => ${$flareGTI}
                    , extension => "STDGTI"
                    , keyword => "ONTIME"
                );
                info(
"Flare screening GTI total time interval is $GTI_time /s."
                );
            }
            ${$flareScreen} = ( $GTI_time > $GTI_time_threshold )
              || !$GTI_time_threshold;
        }
        else
        {
            info("Flare screening GTI too short or empty.");
        }
    }
    else
    {
        info("Flare screening GTI unavailable.");
    }
    if (${$flareScreen})
    {
        push( @{$expr}, "GTI(" . ${$flareGTI} . ",TIME)" );
		ppd( id => '000019');
	setExposureProperty( instrument => thisInstrument , exp_id => $exp_id , name => 'flarescreened' , value => 0+TRUE );
    }
    else
    {
        info("Flare screening will not be applied.");
		ppd( id => '000020');
	setExposureProperty( instrument => thisInstrument , exp_id => $exp_id , name => 'flarescreened' , value => FALSE );
    }
}

sub band8fov
{
    my ( $exp_id, $band, $imgFile, $evFile, $expression, $flareScreen )
      = @_;
    my $gifFile = newFile(
        class => 'intermediate'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , band => $band
        , content => 'image'
        , format => 'GIF'
    );
    my $pngFile = newFile(
        class => 'product'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , band => $band
        , content => 'EPIC image'
        , format => 'PNG'
    );
    doCommand(
        'implot', set => $imgFile
        , device => "$pngFile/PNG"
        , withsrclisttab => 'no'
      )
      or return exception();

#    # Convert to PNG format
#    GIFtoPNG(
#        source => $gifFile
#        , destination => $pngFile
#      )
#      or return exception();

    # Generate truecolor image FITS

    #my $trueColor = newFile(
    #			    class => 'intermediate'
    #    		    , instrument => thisInstrument
    #			    , exp_id => $exp_id
    #			    , format => 'FIT'
    #			    , content => 'Truecolor count rate image'
    #			    );

    #doCommand(
    #	      'etruecolor'
    #	      , tablelist => "${evFile}:EVENTS"
    #	      , fileset => $trueColor
    #	      )
    #	or return exception();
    
    # Generate truecolor image PPM bitmap

    #my $trueColorPPM = newFile(
    #			       class => 'intermediate'
    #			       , instrument => thisInstrument
    #			       , exp_id => $exp_id
    #			       , format => 'PPM'
    #			       , content => 'Truecolor RGB bitmap'
    #			       );

    #my $trueColorRGB = newFile(
    #			       class => 'intermediate'
    #			       , instrument => thisInstrument
    #			       , exp_id => $exp_id
    #			       , format => 'FIT'
    #			       , content => 'Truecolor RGB image'
    #			       );

    #doCommand(
    #	      'etruecolor'
    #	      , tablelist => "${evFile}:EVENTS"
    #	      , ppmfile => $trueColorPPM
    #	      , colorset => $trueColorRGB
    #	      , outputchoice => 'ppmfile'
    #	      )
    #	or return exception();


    return;

    # The following does not seem to be used any more, so the routine now returns beforehand.
    # IMS 2005-11-02
    my $fovFile = newFile(
        class => 'intermediate'
        , instrument => thisInstrument
        , exp_id => $exp_id
        , band => $band
        , content => 'fov image'
    );
    doCommand(
        'evselect'
        ,, table => "${evFile}:EVENTS"
        , imageset => $fovFile
        , xcolumn => 'X'
        , ycolumn => 'Y'
        , withimageset => 'Y'
        , imagebinning => 'binSize'
        , ximagebinsize => 80
        , yimagebinsize => 80
        , squarepixels => 'true'
        , expression => $expression
        , imagedatatype => 'Int32'
        , withimagedatatype => 'true'
        , writedss => 'true'
        , updateexposure => 'true'
        , keepfilteroutput => 'false'
      )
      or return exception();
}
1;