Download

package MakePNImage;
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 = '2.23';
$version = $VERSION;
$author  = 'Richard West,Dean Hinshaw,Duncan John Fyfe,Ian Stewart,Grant Denkinson,Duncan Law-Green,Eduardo Ojero, Ed Chapin, Jose Vicente Perea';
$date    = '2014-10-16';
use Astro::FITS::CFITSIO qw(TRUE FALSE);

#
# ChangeLog
# =========
#
# Version 2.23 - 2014-10-16 (JVP)
# ------------
#
# + Ignore module if no impaging mode is performed
#
# Version 2.22 - 2014-01-18 (EC)
# ------------
#
# + Rules altered to handle EPICImageSize
#
# Version 2.21 - 2013-06-11 (EC)
# ------------
#
# + Merge changes from SOC version.
#
# version 2.20 - 2012-05-03 DLG
# ------------
#
# + Modify examineGTI to use optimised GTI where found
#
# version 2.19 - 2012-05-03 DLG
# ------------
#
# + Eliminate use of GIF bitmaps
#
# version 2.18 - 2012-04-17 DLG
# ------------
# 
# + FIX: Create band-8 non-vig exp map via imweightadd/fcarith (DLG)
#
#
# version 2.17 - 2012-03-26 DLG
# ------------
#
# + Create band-8 non-vig exposure map
# - Disable etruecolor call

#
# version 2.16 - 2011-06-30 DLG
# ------------
#
# + Add call to etruecolor to generate 3-band colour images (DLG)

# version 2.15.1 - 2011-08-09 EOP
# --------------
#
# + Removed creation of GIF files and replaced by direct creation of PNG files.
#
# version 2.15 - 2008-11-26 GD
# ------------
# + fix dark columns problem

#
# version 2.14 - 2006-09-20 DJF
# ------------
#
# + Record EXPOSURE of band 8 image and the state of flarescreening in database.
#
# version 2.13 - 2006-01-20 DJF
# ------------
#
# + Moved isEmageEmpty code to common module library ModuleUtil.
#
# version 2.12 - 2005-11-22 IMS
# ------------
# + Oops, was making the gif of exposure map band 8 (new in version 2.09) but neglected to carry on and make the png.
#
# version 2.11 - 2005-11-16 IMS
# ------------
# + Incorporated DJF's shortened intermediate file names.
#
# version 2.10 - 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.09 - 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.08 - 2005-10-28 IMS
# ------------
#
# + Filtering expression for band 8 and 8fov was 'a && b && (c1 && c2) || (d1 && d2)' etc rather than the correct 'a && b && ((c1 && c2) || (d1 && d2))'. Fixed this.
#
# version 2.07 - 2005-10-20 IMS
# ------------
#
# + Fixed a bug in sub examineGTI (was testing a reference rather than its contents).
#
# version 2.06 - 2005-09-21 IMS
# ------------
#
# + Some bug fixes so it will run.
#
# version 2.05 - 2005-09-21 IMS
# ------------
#
# + More work on the band 8 and band 8fov selection expressions: offset flagging extended to 1keV (band 1 and 2); OOFOV events now retained in band 8 (though not in band 8fov).
#
# version 2.04 - 2005-09-12 IMS
# ------------
#
# + Altered band 8fov selection expression to make it the same as for band 8. The 8fov fits files are only intermediates but they are used to make products (gifs for individual exposures plus the fits mosaic image for the observation).
#
# version 2.03 - 2005-09-05 IMS
# ------------
#
# + More complicated selection expression now used for band 8 (filters out PATTERN>0 and on-offset pixels for PI<500) at request of ACS. We're still waiting for the definitive MPE recommendation for bands 1 and 8.
#
# version 2.02 - 2005-08-12 RGW
# ------------
#
# + band8fov now pays attention to the arguments given to it
# + reinstate filtered image event list
#
# version 2.01 - 2005-06-07 IMS
# ------------
#
# + Commented out %Flag stuff - band-specific selection expressions now obtained by a call.
# + New energy bands temporarily hard-wired until a nice way to accommodate the gap around the Cu line is worked out. Yes I know it is ugly.
# + Test for empty band!=8 image is 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.
# + evselect parameter --squarepixels='y' removed as it has no effect when --imagebinning=='binSize'.
# + --useoffset => 'yes' added to eexpmap calls to match AIP advice (GL email 15 Jun 05).
#
# 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.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 - 2004-Jan-14 (DJF)
# ------------
#
# + Small GTI filtering has been moved to pnEvents module.  We only
#   need 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, amke it more readable and easier to see what selection
#   expressions are used for a given intrument and band.
# + Removed MOS 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 to subroutine
# + Move onOffset construction outside of band loop as it is constant within that loop
#
# 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 = (
#    'epn' => {
#        'default' =>
#          '#XMMEA_EP && ((FLAG & 0x2010024) == 0)' # With OUT_OF_FOV as XMMEA_EP doesn't include it.
#        , '8' => '#XMMEA_EP && ((FLAG & 0x2000024) == 0)'
#        , '8fov' => '#XMMEA_EP && ((FLAG & 0x10000) == 0)'
#    }
#);
#my $pnExtraFlags = [
#    qw(
#      OUT_OF_CCD_WINDOW
#      CLOSE_TO_CCD_WINDOW
#      CLOSE_TO_ONBOARD_BADPIX
#      )
#];

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

# 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, @expmap, @nonVigExpMap, $imFile, $softimFile,
	 $hardimFile );
#    my @expr = ( "(RAWY>12)", "(PATTERN<=4)" );
    my @expr = ( "(RAWY>12)" );

    # Find exposure ID
    my $exp_id = exposureID(
        instrument => thisInstrument
        , stream => thisStream
    );
    my $content = "EPIC PN 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 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 $onOffset    = "((FLAG & "
#      . getEventBitmask(
#        file => $evFile
#        , masks => ['ON_OFFSET_COLUMNS']
#      )
#      . ") == 0)";
    foreach my $band ( 1, 2, 3, 4, 5, 8 )
    {
        info("Band: $band");
        my $filteredList;
        my ($pilo, $pihi, @locexpr) = &getLocExpr($band);

#        # Figure out PI limits for this energy band
#        $pilo = energyBand( $band, 0 );
#        $pihi = energyBand( $band, 1 );
#        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("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 )
        {
            $imFile = $imgFile;
#            push( @locexpr
#                    , "(PI>=500 || (PI<500 && "
#                  . $onOffset
#                  . " && PATTERN==0))" );

	    $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'
		      , withfilteredset => 'Y'
		      , 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 ) )
			{
				($pilo, $pihi, @locexpr) = &getLocExpr('8fov');
				&band8fov(
					$exp_id, $band, $imgFile, $evFile
				, join( '  && ' , @expr, @locexpr , $flareScreen )
				#, join( '  && ' , ( @expr, @locexpr , $Flags{ thisInstrument() }{'8fov'})) , $flareScreen );
				);
			}
		}
        else
        {
            $filteredList = newFile(
                class => 'intermediate'
                , instrument => thisInstrument
                , exp_id => $exp_id
                , band => $band
                , content => 'image event list'
            );

	    if ( $band == 2 )
	    {
		$softimFile = $imgFile; # band 2 image
	    }

	    if ( $band == 3 )
	    {
		$hardimFile = $imgFile; # band 3 image
	    }

#            if ( $band == 1 )
#            {
#                push( @locexpr, ( 'PATTERN==0', $onOffset ) );
#            }
            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();
        push( @ebandlo, $pilo );
        push( @ebandhi, $pihi );
    }    #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();
    }
    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 non-vignetted 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
    doCommand(
	      'eexpmap', imageset => $softimFile
	      , eventset => $evFile
	      , attitudeset => $attFile
	      , attrebin => 2
	      , expimageset => [@expmap[0 .. 1]]
	      , pimin => [@ebandlo[0 .. 1]]
	      , pimax => [@ebandhi[0 .. 1]]
	      , withvignetting => 'yes'
	      )
	or return exception();
    
    # Run exposure map task to generate all exposure maps in parallel
    doCommand(
	      'eexpmap', imageset => $hardimFile
	      , eventset => $evFile
	      , attitudeset => $attFile
	      , attrebin => 2
	      , expimageset => [@expmap[2 .. 4]]
	      , pimin => [@ebandlo[2 .. 4]]
	      , pimax => [@ebandhi[2 .. 4]]
	      , withvignetting => 'yes'
	      )
	or return exception();

    # Run exposure map task to generate all non-vig exposure maps in parallel
    doCommand(
	      'eexpmap', imageset => $softimFile
	      , eventset => $evFile
	      , attitudeset => $attFile
	      , attrebin => 2
	      , expimageset => [@nonVigExpMap[0 .. 1]]
	      , pimin => [@ebandlo[0 .. 1]]
	      , pimax => [@ebandhi[0 .. 1]]
	      , withvignetting => 'no'
	      )
	or return exception();
    
    doCommand(
	      'eexpmap', imageset => $hardimFile
	      , eventset => $evFile
	      , attitudeset => $attFile
	      , attrebin => 2
	      , expimageset => [@nonVigExpMap[2 .. 4]]
	      , pimin => [@ebandlo[2 .. 4]]
	      , pimax => [@ebandhi[2 .. 4]]
	      , withvignetting => 'no'
	      )
	or return exception();

    # Make band 8 image - add five images without weighting then divide by 5 to get mean    

    my $addedexpmaps = newFile(
			      class => 'intermediate'
			      , instrument => 'epic'
			      , content => 'temporaryImage'
			      );
    
    doCommand(
	       'imweightadd'
	      , imagesets => [@expmap[0 .. 4]]
#	      , calculateweights => 'no' # in docs but throws exception invalidOption
	      , withweights => 'no' # as used in ExpDetect.pm
	      , outimageset => $addedexpmaps
	      )
	or return exception();

    doCommand(
	      'fcarith'
	      , infile => $addedexpmaps
	      , const => 5
	      , outfil => @expmap[5]
	      , ops => 'DIV'
	      )
	or return exception();    


    my $addednonvigexpmaps = newFile(
				     class => 'intermediate'
				     , instrument => 'epic'
				     , content => 'temporaryImage2'
				     );

    doCommand(
	      'imweightadd'
	      , imagesets => [@nonVigExpMap[0 .. 4]]
	      , withweights => 'no'
	      , outimageset => $addednonvigexpmaps
	      );

    doCommand(
	      'fcarith'
	      , infile => $addednonvigexpmaps
	      , const => 5
	      , outfil => @nonVigExpMap[5]
	      , ops => 'DIV'
	      )
	or return exception();


# alternate way setting tempset for imweightadd and using farith instead of fcarith
#    my $tempImage = newFile(
#			    class => 'intermediate'
#			    , instrument => 'epic'
#			    , content => 'temporaryImage'
#			    );
#    doCommand(
#	      'imweightadd'
#	      , imagesets => @expmap[0 .. 4]
#	      , calculateweights => 'no'
#	      , outimageset => $addedexpmaps
#	      , tempset => $tempImage
#	      )
#	or return exception();
#    doCommand(
#	      'farith'
#	      , infil1 => $addedexpmaps
#	      , infil2 => 5
#	      , outfil => @expmap[5]
#	      , ops => 'DIV'
#	      )
#	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();

#    # 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 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} ) )
    {

        # Find intersection between attitude and flage GTI
        #my $attFlareGti = newFile(class => 'intermediate'
        #	,instrument => thisInstrument
        #	,exp_id => $exp_id
        #	,content => 'EPIC Attiture and Flare GTI Intersect'
        #);
        # 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)
    if (${$flareScreen})
    {
		ppd( id => '000017' );
        push( @{$expr}, "GTI(" . ${$flareGTI} . ",TIME)" );
	setExposureProperty( instrument => thisInstrument , exp_id => $exp_id , name => 'flarescreened' , value => 0+TRUE );
    }
    else
    {
		ppd( id => '000018' );
        info("Flare screening will not be applied.");
	setExposureProperty( instrument => thisInstrument , exp_id => $exp_id , name => 'flarescreened' , value => FALSE );
    }

}

sub band8fov
{
    my ($exp_id, $band, $imgFile, $evFile, $expression, $flareScreen)=@ARG;

    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();

    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();
}

sub getLocExpr
{
    my ( $band ) = @_;

    my ($pilo, $pihi, @locexpr);

    if ( $band eq '1' )
    {
        $pilo = 200;
        $pihi = 500;
        push @locexpr, 'PATTERN==0';
        push @locexpr, 'PI in (200:500]';
        push @locexpr, '(FLAG & 0x2fb002c)==0';
#### MPE are supposed to be going to suggest some better scheme for bands 1 and 8. Haven't got it from them yet though. IMS 2005-08-02.
    }
    elsif ( $band eq '2' )
    {
        $pilo = 500;
        $pihi = 1000;
        push @locexpr, 'PATTERN<=4';
        push @locexpr, 'PI in (500:1000]';
        push @locexpr, '(FLAG & 0x2fb002c)==0';
    }
    elsif ( $band eq '3' )
    {
        $pilo = 1000;
        $pihi = 2000;
        push @locexpr, 'PATTERN<=4';
        push @locexpr, 'PI in (1000:2000]';
        push @locexpr, '(FLAG & 0x2fb0024)==0';
    }
    elsif ( $band eq '4' )
    {
        $pilo = 2000;
        $pihi = 4500;
        push @locexpr, 'PATTERN<=4';
        push @locexpr, 'PI in (2000:4500]';
        push @locexpr, '(FLAG & 0x2fb0024)==0';
    }
    elsif ( $band eq '5' )
    {
        $pilo = 4500;
        $pihi = 12000;
        push @locexpr, 'PATTERN<=4';
        push @locexpr, '(PI in (4500:7800] || PI in (8200:12000])';
        push @locexpr, '(FLAG & 0x2fb0024)==0';
    }
    elsif ( $band eq '6' )
    {
        return exception();
    }
    elsif ( $band eq '7' )
    {
        return exception();
    }
    elsif ( $band eq '8' )
    {
        $pilo = 200;
        $pihi = 12000;
#        push @locexpr, 'PATTERN<=4';
#        push @locexpr, 'PI in (200:12000]';
#        push @locexpr, '(FLAG & 0x2fa002c)==0';
push @locexpr, "((PATTERN==0 && PI in  (200:500]   && (FLAG & 0x2fa002c)==0)"
          ." || (PATTERN<=4 && PI in  (500:1000]  && (FLAG & 0x2fa002c)==0)"
          ." || (PATTERN<=4 && PI in (1000:12000] && (FLAG & 0x2fa0024)==0))";
#### MPE are supposed to be going to suggest some better scheme for bands 1 and 8. Haven't got it from them yet though. IMS 2005-08-02.
#### Now we have the MPE scheme but have decided not to use it to filter events; sources near these columns will be flagged instead. IMS 2005-09-21.
    }
    elsif ( $band eq '8fov' )
    {
        $pilo = 200;
        $pihi = 12000;
#        push @locexpr, 'PATTERN<=4';
#        push @locexpr, 'PI in (200:12000]';
#        push @locexpr, '(FLAG & 0x0fb0000)==0';
push @locexpr, "((PATTERN==0 && PI in  (200:500]   && (FLAG & 0x2fb002c)==0)"
          ." || (PATTERN<=4 && PI in  (500:1000]  && (FLAG & 0x2fb002c)==0)"
          ." || (PATTERN<=4 && PI in (1000:12000] && (FLAG & 0x2fb0024)==0))";
    }
    elsif ( $band eq '9' )
    {
        return exception();
    }
    else
    {
        return exception();
    }

    return ($pilo, $pihi, @locexpr);
}
1;