package RGSEvents; use strict; use English; use Carp; use vars qw(@ISA $VERSION $name $author $date $version @instList $numberOfStreams); @ISA = qw(Module); use ModuleResources; $name = __PACKAGE__; $VERSION = '4.18'; $version = $VERSION; $author = 'Duncan John Fyfe,Dean Hinshaw,Ian Stewart'; $date = '2007-01-23'; # # ChangeLog # ========= # # version 4.18 - 2007-01-23 DJF # ------------ # # + Changed source selection to PRIMESRC + Brightest EPIC source with FLAG == 0 && RATE > rate_cutoff && INDEX != PRIMESRC # + Where we have and EPIC source list add keywords EPMINRTE and EPRGSRCN to reflect the EPIC rate cutoff and the # number of EPIC sources which could have been selected by the above expression. # + Changed to make cross-dispersion histogram for selected RGS sources rather than trying to guess. # + Added attfilter to create an exposure limited GTI and change call to rgssources to use 'expmedian'.. # # version 4.17 - 2006-10-25 DJF # ------------ # # + Add FILTGRPS keyword to filtered event list. This record which rgsfilter groups have been applied (rejflags=1|AttGTI=2|hkGTI=4). # # version 4.16 - 2006-09-13 DJF # ------------ # # + Now make Cross-dispersion histogram for the first one of source number 1 , 3 2 (in that order). # # version 4.15 - 2006-09-07 DJF # ------------ # # + Added withmlambdacolumn => 'Y' to rgsangles as recommended by Andy Pollock. # # version 4.14 - 2006-08-11 DJF # ------------ # # + Moved event list and exposure map decleration after the empty HK GTI test. # # version 4.13 - 2006-07-28 DJF # ------------ # # + Implemented plan B event filtering. Cut down on GTI's applied until # none are left. If still < thesholf GTI don't so any further processing. # # version 4.12 - 2006-07-06 DJF # ------------ # # + Test for empty event list moved after ONTIME test. It may not be necessary but belt and braces never hurts. # # version 4.11 - 2006-07-01 DJF # ------------ # # + Updated parameters to reflect changes to rgsproc-1.24.1 # # version 4.10 - 2006-06-15 DJF # ------------ # # + Use rgsfilter generated ONTIME keyword. If ONTIME < threshhold do not use filtered event list. # # version 4.09 - 2005-11-23 DJF # ------------ # # + Xdisp histogram content string altered (to include the 'cross'), also the file name now includes order and source number. # # version 4.08 - 2005-11-09 DJF # ------------ # # + rgsregions parameter procsrcsexpr had an invalid value # causing bad parsing of the command line # was "LABEL==\'WHOLE_FIELD\'" now 'LABEL == "WHOLE_FIELD"' # + Remove excessinve ) from last evselect expression # # version 4.07 - 2005-11-09 DJF # ------------ # # + Module now raises an exception if rgssources fails. # rather than setting itself to ignored. # # version 4.06 - 2005-10-28 DJF # ------------ # # + The module now sets itself to ignored when rgssources fails. # This is to allow testing of later EPIC and OM modules. # while the rgssources problem is worked on. # # version 4.05 - 2005-10-28 IMS # ------------ # # + Added call to make dispersion histogram as requested by AP. # # version 4.04 - 2005-10-17 IMS # ------------ # # + Added extra call to rgssources to create the row in the source list which will generate the 'whole-field' spectrum. # + Removed a lot of commented-out code. # + Added copyFile to the list of used ModuleResources subs. # # version 4.03 - 2005-09-21 IMS # ------------ # # + Code was in a funny state - as if I had inadvertently overwritten much of my previous mods. I've tried to put it back in the intended state. # # version 4.02 - 2005-09-20 IMS # ------------ # # + rgssources now uses the observation-level emldetect source list. This replaces the complicated searching for the best exposure-level list. # # version 4.01 - 2005-08-08 IMS # ------------ # # + Parameter --withdiagoffset of rgsenergy => 'yes' (recommendation of Andy Pollock of SOC on 5 Aug 2005). # # version 4.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 3.23 - 15-Mar-2004 (DJF) # ------------------------------- # # + reverted rgssources:attstyle=expmedian changed to median # We are not yet producing a necessary Attitude data set for this to work. # # Version 3.22 - 04-Mar-2004 (DJF) # ------------------------------- # # + rgscources:attstyle=median changed to expmedian # # Version 3.21 - 24-Feb-2004 (DJF) # ------------------------------- # # evlistcomb, change rgsdatamodes value 'HIGH TIME RESOLUTION' to 'HIGHTIMERESOLUTION' # See SSC-SPR-3256 # # Version 3.20 - 21-Feb-2004 (DJF) # ------------------------------- # # + Accidentally left NEXT_TO_CCD_BORDER in rgsfilter:rejflag # # Version 3.19 - 21-Feb-2004 (DJF) # ------------------------------- # # + Changed rgsfilter rejflags. Replaced depreciated NEXT_TO_CCD_BORDER # with ON_NODE_INTERFACE and ON_WINDOW_BORDER # # Version 3.18 - 20-Feb2004 (DJF) # ------------------------------- # # + Explicitly pass rgsdatamodes parameters to evlistcomb to overcome # bug with default values. # # Version 3.17 - 20-Feb2004 (DJF) # ------------------------------- # # + Updated rgssources parameter, atthkset => medianset # # Version 3.16 - 10-Dec-2003 (DJF) # ------------------------------- # # + Adapted doCommand to use anonymous lists for list parameters. # # Version 3.15 - 11-Apr-2003 (DJF) # ------------------------------- # # + Add EXPIDSTR to flare background via addattribute # # Version 3.14 - 11-Nov-2002 (DJF) # ------------------------------- # # + Added writedss => N and updateexposure => N to flare background # creating evselect # # Version 3.13 - 4-Nov-2002 (DJF) # ------------------------------- # # + Added region X & Y axis to background timeseries creation to supress # an error message. # # Version 3.12 - 31-Oct-2002 (DJF) # ------------------------------- # # + Added exception call for background timeseries creation errors # # Version 3.11 - 31-Oct-2002 (DJF) # ------------------------------- # # + Added RGS flare background timeseries # # Version 3.10 - 04-July-2002 (DJF) # ------------------------------- # # + rgssources attstyle=mean changed to attstyle=median # # Version 3.09 - 16-Apr-2002 (DH) # ------------------------------- # # + Trap case where final event list is empty, and don't do # any further processing. # # Version 3.08 - 12-Mar-2002 (DH) # ------------------------------- # # + Set rgssources enablefilter option to be true in all cases. # # Version 3.07 - 07-Mar-2002 (DH) # ------------------------------- # # + Add FLAG==0 to source selection expression for rgsregions. # # Version 3.06 - 25-Feb-2002 (DH) # ------------------------------- # # + Turn on source confusion checking in rgssources. # # Version 3.05 - 19-Feb-2002 (DH) # ------------------------------- # # + Stop processing before rgsfilter call if rgs hk gti file is empty. # # Version 3.04 - 06-Feb-2002 (DH) # ------------------------------- # # + Change evaluateRules so this module depends on InstrumentHK for this # exposure. # # Version 3.03 - 06-Feb-2002 (DH) # ------------------------------- # # + Bug fixes for 3.02 # # Version 3.02 - 05-Feb-2002 (DH) # ------------------------------- # # + Change priorities on which EPIC source list to use. Now all MOS imaging modes # have priority over PN full frame modes, whereas previously the PN full frame # had priority over MOS large and small window. # + Updates to bring in line with rgsproc 1.3 . # # Version 3.01 - 24-Oct-2001 (DH) # ------------------------------- # # + Bug fixes for version 3.00 . # # Version 3.00 - 19-Oct-2001 (DH) # ------------------------------- # # + Rework to bring in line with rgsproc 0.107, and the new # versions of associated rgs tasks. # # Version 2.21 - 1-Oct-2001 (DH) # ------------------------------- # # + Replace dslatts call with the hasFITSExtension function. # # Version 2.20 - 15-Aug-2001 (DJF) # ------------------------------- # # + Add fudge for rgssources. v 5.2.3 expects the exposure id as an integer the leading S is hardcoded into the task. # It does not handle unsheduled exposures. # # Version 2.19 - 13-Aug-2001 (DJF) # ------------------------------- # # + Removed redundant evselect filtering before call to rgssources. The filtering is done by rgssources. # # Version 2.18 - 09-Aug-2001 (DJF) # ------------------------------- # # + Amended parameters passed to rgssources to fit with v 5.2 # # Version 2.17 - 29-May-2001 (DJF) # ------------------------------- # # Removed filtering on band 1 from evselect. # Added updateexposure=>'no' to evselect # # Version 2.16 - 21-May-2001 (DJF) # ------------------------------- # # + Added 'primestyle=>brightest' to rgssources # # Version 2.15 - 18-May-2001 (DH) # ------------------------------- # # + Remove rgsoffset call, as the output files # never get used. # # Version 2.0 - 01-May-2001 (DJF) # ------------------------------- # # + Initial Version. Change required by SAS 5.1 # # Version 1.13 - 2001-03-21 (DH) # ------------ # # + Filter event lists with GTI for good attitude # data. # # Version 1.12 - 2001-03-16 (DH) # ------------ # # + Print out version number in performAction() for # tracking purposes. # # Version 1.11 - 2001-03-12 (DH) # ------------ # # + Change from using 'rgsregion' and 'rgsbackreg' to 'rgsregions'. # # Version 1.10 - 2001-02-01 (DH) # ------------ # # + Change rate cut in rgssources from 0.4 to 0.2 . # # Version 1.09 - 2001-02-01 (DH) # ------------ # # + Change rate cut in rgssources from 0.05 to 0.4 . # # Version 1.08 - 2001-01-31 (DH) # ------------ # # + Bug fixes for version 1.07 # # Version 1.07 - 2001-01-31 (DH) # ------------ # # + Expand RGS fov from 2 acrmins to 5 arcmins. # Arrange evselect and rgssources calls so that the brightess source # in the RGS fov always gets a spectrum. Result is that only sources # in the RGS fov make it into the RGS srouce list. # # Version 1.06 - 2001-01-26 (DH) # ------------ # # + If there is a suitable EPIC source list, use sources in the # RGS fov. Do not force a spectra for the brightest source. If # there is no suitable EPIC source list, take the pointing position # as the only source. # # Version 1.05 - 2001-01-24 (DH) # ------------ # # + Check for existance of epic source list before trying to use it. # # Version 1.04 - 2000-12-18 (DH) # ------------ # # Declare instruments of interest @instList = qw(rgs1 rgs2); # Number of Streams sub numberOfStreams { return numberOfExposures(); } # Rules evaluated to determine when this modules can run. sub evaluateRules { # If upstream module has been ignored, so if this one return ignore() if ignored( module => 'ExpChooser' , instrument => thisInstrument , stream => thisStream ); # return start() if complete( module => 'GlobalHK' , instrument => 'all' , stream => 1 ) and complete( module => 'InstrumentHK' , instrument => thisInstrument , stream => 1 ) and complete( module => 'ExpChooser' , instrument => thisInstrument , stream => thisStream ) and allComplete( module => 'ExpDetect' ); } # The guts of the module sub performAction { info("Module version number: $version"); my $srcSelectionExpression; my @process_source; # Work out which exposure this stream maps on to my $exp_id = exposureID( instrument => thisInstrument , stream => thisStream ); info("Exposure ID: $exp_id"); # Fetch instrument mode (for info. only) my $mode = getExposureProperty( exp_id => $exp_id , name => 'mode' ); info("Instrument mode: $mode"); # # Get list of RGS event files to be processed. # # Find event files for this exposure my @evFiles = findFile( class => 'ODF' , instrument => thisInstrument , exp_id => $exp_id , content => '*events' ); # Return immediately if there are no event files unless (@evFiles) { info("No event files found"); return success(); } # # Get attitude history file # my $attFile = findFile( class => 'product' , instrument => 'all' , content => 'Attitude time series' , required => 'Y' ); # Create an exposure limited attitude GTI. # Need to construct a 6 character instexpid string for attfilter. my $instexpid = thisInstrument; $instexpid =~ /([12])/; $instexpid = "R$1$exp_id"; my $expAttGTI = newFile( class => 'intermediate' , instrument => thisInstrument , exp_id => $exp_id , content => 'Exposure Attitude GTI' ); # filtertype ass rgsproc # tolangles: rgsproc has a parameter driftlimit which is converted internally to a tolangles entry of "float(X)*#ARCMIN" # driftlimit=float(X) becomes doCommand('attfilter' ,instexpid => $instexpid ,attset => $attFile ,gtitable => "$expAttGTI:STDGTI" ,filtertype => 'cone' ,tolangles => '5.0*#ARCMIN' ) or return exception(); # # Get Good Time Interval # my $goodAttGTI = findFile( class => 'intermediate' , instrument => 'all' , content => 'Attitude GTI' , required => 'Y' ); # # Find observation-level EPIC Source list # my $epicList = findFile( class => 'product' , instrument => 'epic' , content => 'EPIC observation ml source list' ); my $haveEpicList = fileExists(file => $epicList); # Check that the epic source list exists. If not, just use pointing position. my $srcFile = newFile( class => 'product' , instrument => thisInstrument , exp_id => $exp_id , content => 'RGS source list' ); my $primesrc; my @rgssources = ( instexpid => $evFiles[0] , filemode => 'create' , medianset => $attFile , srclist => $srcFile , expmediantable => "$expAttGTI:STDGTI" , attstyle => 'expmedian' , primestyle => 'auto' , doconfusion => 'Y' , enablefilter => 'Y' , flagepicsrcoutoffov => 'Y' ); if ( $haveEpicList ) { push @rgssources , withepicset => 'Y' , epicset => $epicList.":SRCLIST"; } else { info( "No suitable EPIC source list found to supply source positions"); info("Using pointing position instead"); push @rgssources , withepicset => 'N'; } doCommand( 'rgssources' , @rgssources ) or return exception() ; my @srcindex; my $rate_cutoff = 0.2; ( $srcSelectionExpression , @srcindex ) = ModuleUtil::select_rgssources( $srcFile , 'SRCLIST' , $haveEpicList , $rate_cutoff ); # # Generate RGS source list # my $wholeFieldSrcFile = newFile( class => 'intermediate' , instrument => thisInstrument , exp_id => $exp_id , content => 'RGS src list with whole field' ); copyFile(source => $srcFile, destination => $wholeFieldSrcFile); doCommand( 'rgssources' , srclist => "${wholeFieldSrcFile}:SOURCES" , filemode => 'modify' , addusersource => 'yes' , label => 'WHOLE_FIELD' , positionstyle => 'wrtatt' , deltadisp => 0.0 , deltaxdsp => 0.0 , process => 'no' , bkgexclude => 'no' ) or return exception(); # # Process Events on a per CCD basis # my @evList; foreach my $evFile0 (@evFiles) { # Find CCD number my $ccd = readFITSKeyword( file => $evFile0 , extension => 2 , keyword => "CCDID" ); info("Processing CCD $ccd"); my $evFile1 = newFile( class => 'intermediate' , instrument => thisInstrument , exp_id => $exp_id , ccd => $ccd , content => 'Intermediate events' , level => 1 ); # Run rgsframes # doCommand( 'rgsframes' , set => $evFile0 , ccdset => $evFile1 ) or return exception(); # Run rgsenergy # doCommand( 'rgsenergy' , ccdset => $evFile1 , withdiagoffset => 'yes' ) or return exception(); # Run rgsbadpix # doCommand( 'rgsbadpix', ccdset => $evFile1 , keepcool => 'Y' ) or return exception(); # Run rgsevents # doCommand( 'rgsevents', ccdset => $evFile1 ), or return exception(); push( @evList, $evFile1 ); } # # Merge Event Lists # my @mainattributes = ( "CCDOCB", "SOURCEID", "DATE-OBS", "DATE-END" , "DATATYPE", "TSTART", "TSTOP", "TELAPS" , "XMMEA_RG" ); my @othertables = ( "STDGTI", "BADPIX0", "BADPIX1", "REJPIX0" , "REJPIX1", "EXPOSURE" ); my @rgsimgcolnames = ( "TIME", "FLAG", "BETA", "XDSP", "CHIPX", "CHIPY" , "PHA", "SHAPE", "GRADE", "PI" ); my @rgsimgcoltypes = ( "double", "int32", "single", "single", "int16", "int16" , "int16", "int8", "int8", "int16" ); my $combList = newFile( class => 'intermediate' , instrument => thisInstrument , exp_id => $exp_id , content => 'Event list' ); doCommand( 'evlistcomb', eventsets => [@evList] , instrument => 'rgs' , imagingset => $combList , mainattributes => [@mainattributes] , othertables => [@othertables] , rgsimgcolnames => [@rgsimgcolnames] , rgsimgcoltypes => [@rgsimgcoltypes] , rgsdatamodes => [ 'SPECTROSCOPY', 'HIGHTIMERESOLUTION' ] ) or return exception(); # # Process Sources # # # Run rgsangles # doCommand( 'rgsangles' , mergedset => $combList , srclist => $srcFile , betabinning => 'binSize' , betabinref => 3.578524e-2 , betabinwidth => 1.208e-5 , nbetabins => 3400 , nxdispbins => 170 , xdispbinning => 'binSize' , xdispbinref => -9.126e-4 , xdispbinwidth => 1.08e-5 , withmlambdacolumn => 'Y' ) or return exception(); # # Do exposure/event filtering plus much much more # my $hkgtiFile = findFile( class => 'intermediate' , instrument => thisInstrument , content => 'HK GTI' ); unless ( numberFITSRows( file => $hkgtiFile, extension => 'STDGTI' ) ) { info( "RGS HK GTI file is empty. No more processing will be done." ); return success(); } my $filteredEventList = newFile( class => 'intermediate' , instrument => thisInstrument , exp_id => $exp_id , content => 'FILTERED EVENT LIST' ); my $expFile = newFile( class => 'product' , instrument => thisInstrument , exp_id => $exp_id , content => 'RGS EXPOSURE MAP' ); my @rejflags = ( 'BAD_SHAPE', 'ON_BADPIX' , 'NEXT_TO_BADPIX', 'BELOW_ACCEPTANCE' , 'ON_NODE_INTERFACE', 'ON_WINDOW_BORDER' ); info("Filtering with rejection flags, Attitude GTI and HK GTI."); my ($rejflags_f , $goodAttGTI_f , $hkgtiFile_f) = (1 , 2 , 4); my $rgsfilter_f = $rejflags_f | $goodAttGTI_f | $hkgtiFile_f ; doCommand( 'rgsfilter' , mergedset => $combList , evlist => $filteredEventList , rejflags => [@rejflags] , auxgtitables => [ $expAttGTI ,$goodAttGTI, $hkgtiFile ] , withexpmaps => 'Y' , withcombmap => 'Y' , expimageset => $expFile ) or return exception(); # Use ONTIME to decide whether to use the unfiltered/filtered event list. my $ontime_threshold = 1000; my $ontime = readFITSKeyword( file => $filteredEventList , extension => "EVENTS" , keyword => "ONTIME" ); if ( $ontime < $ontime_threshold) { $rgsfilter_f = $rejflags_f | $goodAttGTI_f; ppd(id => "000014", data => { ontime => $ontime , threshold => $ontime_threshold } ); info("Filtering with rejection flags, Attitude GTI and HK GTI leaves < 1000s ONTIME."); info("Filtering with rejection flags and Attitude GTI."); unlink ( $filteredEventList ); doCommand( 'rgsfilter' , mergedset => $combList , evlist => $filteredEventList , rejflags => [@rejflags] , auxgtitables => [ $expAttGTI , $goodAttGTI ] , withexpmaps => 'Y' , withcombmap => 'Y' , expimageset => $expFile ) or return exception(); $ontime = readFITSKeyword( file => $filteredEventList , extension => "EVENTS" , keyword => "ONTIME" ); if ( $ontime < $ontime_threshold) { $rgsfilter_f = $rejflags_f; ppd(id => "000015", data => { ontime => $ontime , threshold => $ontime_threshold } ); info("Filtering with rejection flags and Attitude GTI leaves < 1000s ONTIME."); info("Filtering with rejection flags."); unlink ( $filteredEventList ); doCommand( 'rgsfilter' , mergedset => $combList , evlist => $filteredEventList , rejflags => [@rejflags] , auxgtitables => [ $expAttGTI ] , withexpmaps => 'Y' , withcombmap => 'Y' , expimageset => $expFile ) or return exception(); $ontime = readFITSKeyword( file => $filteredEventList , extension => "EVENTS" , keyword => "ONTIME" ); if ($ontime < $ontime_threshold) { $rgsfilter_f = 0; ppd(id => "000016", data => { ontime => $ontime , threshold => $ontime_threshold } ); info("Filtering with rejection flags leaves < 1000s ONTIME."); } } } # Record the filter selection in several places. info("ONTIME=$ontime"); info("FILTGRPS=$rgsfilter_f"); setExposureProperty( instrument => thisInstrument , exp_id => $exp_id , name => 'filtgrps' , value => $rgsfilter_f ); # Add the filter flag to the event list. doCommand( 'addattribute', set => $filteredEventList , attributename => 'FILTGRPS' , attributetype => 'integer' , attributecomment => "\"\\\"rgsfilter groups applied (rejflags=1|AttGTI=2|hkGTI=4)\\\"\"" , integervalue => $rgsfilter_f ); # Stop here if we don't have enough ONTIME. if ($ontime < $ontime_threshold) { info("Filtering with rejection flags < 1000s GTI."); info("Ignoring this exposure."); return success(); } my $finalEventList = newFile( class => 'product' , instrument => thisInstrument , exp_id => $exp_id , content => 'RGS EVENT LIST' ); copyFile( source => $filteredEventList , destination => $finalEventList ); # If the event list is empty, don't do any more processing. return success() if ( numberFITSRows( file => $finalEventList , extension => 'EVENTS' ) == 0); # # Process Regions # doCommand( 'rgsregions' , procsrcsexpr => $srcSelectionExpression , exclsrcsexpr => $srcSelectionExpression , setflags => 'Y' , evlist => $finalEventList , srclist => $srcFile ) or return exception(); doCommand( 'rgsregions' , srclist => $wholeFieldSrcFile , procsrcsexpr => 'LABEL == "WHOLE_FIELD"' , xpsfabove => 100 , xpsfbelow => 100 , xpsfexcl => 98 , setflags => 'Y' , evlist => $finalEventList ) or return exception(); # # Generate flare background time series my $flarebkg = newFile( class => 'product' , instrument => thisInstrument , exp_id => $exp_id , content => 'RGS FLARE BACKGROUND TIMESERIES' ); my $bgtable = uc(thisInstrument) . "_BACKGROUND"; doCommand( 'evselect', table => $finalEventList , timebinsize => 100 , withrateset => 'Y' , rateset => $flarebkg , makeratecolumn => 'Y' , maketimecolumn => 'Y' , expression => "(CCDNR==9) && (REGION(${srcFile}:$bgtable,BETA_CORR,XDSP_CORR))" , writedss => 'N' , updateexposure => 'N' ) or return exception(); doCommand( 'addattribute', set => $flarebkg , attributename => 'EXPIDSTR' , attributetype => 'string' , stringvalue => "$exp_id" ); # Create the dispersion histogram: foreach my $srcnum ( @srcindex ) { my $src1RegionExtension = uc(thisInstrument) . "_SRC${srcnum}_ORDER_1"; if (!hasFITSExtension( file => $srcFile , extension => $src1RegionExtension)) { info("Can't find extension $src1RegionExtension in source list $srcFile"); } else { my $histogram = newFile( class => 'product' , instrument => thisInstrument , exp_id => $exp_id , src_num => $srcnum , order => 1 , rgsorder => 1 , content => 'RGS CROSS-DISPERSION HISTOGRAM' ); doCommand( 'evselect', table => $finalEventList , expression => "REGION(${srcFile}:${src1RegionExtension},BETA_CORR,PI)" , filtertype => 'expression' , histogramset => $histogram , histogramcolumn => 'XDSP_CORR' , histogrambinsize => 1.0800000382e-05 ) or return exception(); ppd( id => "000025", data => { srcnum => $srcnum }); } } # return success(); } 1;