XMM-Newton Science Analysis System
emchain (emchain-12.1) [22.0.0-9173c7d25-20250127]
Algorithm
subroutine emchain
Read parameters.
if startfromodf then call processOdf
else if runevlistcomb then call mergeEvents
if makeflaregti then
Loop over the *MIEVLI0000.FIT files
call makeFlareTS
if globalflare call mergeTS else call tsToGTI
end loop
if globalflare call tsToGTI
endif
Loop over the *MIEVLI0000.FIT files
if addtaglenoise call emtaglenoise
if withflaregti call applyFlareGTI
if addvigweight call evigweight ineventset=eventfile
end loop
if not keepintermediate then rm -f *.in.mos *.out.mos merged.*.mos
end subroutine emchain
subroutine processOdf
Set SAS_ODF to odf (for OAL).
Call atthkgen if no tracking history file or withatthkgen is true.
Call tabgtigen with expression='!isNull(DAHFPNT) && DAHFPNT<atttol'
Call hkgtigen if no HK GTI is present.
gtiext = 'T' // obsid // inst // 'X000EXTGTI0000'.FIT'
Call gtimerge gtitable=$gtiext on attitude GTI (if filteratt),
HK GTI (if filterhk) and user GTI (if present)
Look in odf for ODF files pertaining to selected instrument,
ending in IME, TIE, RIE or CTE.FIT (possibly .gz or .FTZ).
Deduce all exposures present.
Loop over selected exposures
if badpixfindalgo ne 'NO' then
call ccdLoop (forbadpixfind=Y)
call badpixLoop (no flare screening)
call mergeEvents
call ebadpixpixupdate
call buildFlareGTI
call badpixLoop (with flare screening and low energy run)
endif
call ccdLoop (forbadpixfind=N)
if runevlistcomb then call mergeEvents
end loop over exposures
end subroutine processOdf
subroutine ccdLoop
Loop over selected CCDs and nodes
Identify event file name event0 ending in IME, TIE, RIE or CTE.FIT.
Deduce ccd and node. nccd = node // ccd
core = obsid // inst // expid
aux = substring($event0 - last 9 characters) // '00AUX.FIT'
gtiin = 'T' // core // 'RAWGTI00' // nccd // '.FIT'
gtiout = 'T' // core // 'LOCGTI00' // nccd // '.FIT'
frameout = 'T' // core // 'FRAMLI00' // nccd // '.FIT'
eventin = 'T' // core // 'RWEVLI00' // nccd // '.FIT'
eventout = 'T' // core // 'CLEVLI00' // nccd // '.FIT'
eventcal = 'T' // core // 'CAEVLI00' // nccd // '.FIT'
emframes auxiliaryset=frame.in odfeventset=$event0 \
outeventset=$eventin frameset=$frameout outgtiset=$gtiin
if ($gtiext exists) then
flagbadtimes=Y ingtiset=$gtiext
if (not processlowgain and GAIN_CCD='LOW') next
bad = 'T' // core // 'BPXFLI00' // nccd // '.FIT'
if $bad does not exist then
bad = 'P*' // instid // '*BADPIX00' // nccd // '.FIT'
if withbadpix and not forbadpixfind then
mv $eventin $eventout
badpix eventset=$eventout outset=$eventin windowfilter=Y
if ($bad exists) then
getuplnkbadpix=Y getotherbadpix=N getnewbadpix=Y badpixset=$bad
rm $eventout
endif
off = odf // * // instrument // * // ccd // node // 'OVE.FIT'
emevents frameset=$frameout odfeventset=$eventin eventset=$eventout
if ($off exists) then offvarsets=$off
if not randomizeP then randomizeposition=N
if randomizeT then randomizetime=Y
if forbadpixfind then analysepatterns=N flagbadpixels=N \
splitdiagonals=N randomizeposition=N
if ($gtiext exists) then
hkgti = 'T' // core // 'HKXGTI00' // nccd // '.FIT'
gtialign gtitable=$gtiext:STDGTI eventset=$eventout \
outset=$hkgti
extname = 'STDGTI' // node // ccd
gtimerge tables="$hkgti $gtiin" mergemode=and \
gtitable=$gtiout:$extname
cp $eventout $eventcal
if withattcalc and not forbadpixfind then
attcalc eventset=$eventcal
emenergy ineventset=$eventcal
if not imaging mode then getccdbkg=N
if not randomizeE then randomizeenergy=N
if forbadpixfind then correctcti=N correctgain=N randomizeenergy=N
bkg = 'P' // core // 'CCDBKG00' // nccd // '.FIT'
if writeccdbackground then backgroundset=$bkg
if rejectbadevents or forbadpixfind then
evselect table=$eventcal destruct=Y keepfilteroutput=Y \
expression="(FLAG & 0x$rejectionflag) == 0"
end loop over CCDs and nodes
end subroutine ccdLoop
subroutine badpixLoop
Loop over selected CCDs and nodes
bad = 'T' // core // 'BPXFLI00' // nccd // '.FIT'
eventfilt = 'T' // core // 'FTEVLI00' // nccd // '.FIT'
evmap = 'T' // core // 'IMAGPR00' // nccd // '.FIT'
evselect table=$eventcal filteredset=$eventfilt \
keepfilteroutput=Y destruct=Y writedss=Y updateexposure=Y \
expression="TIME in GTI($gtiflare)"
if badpixfindalgo == 'EM' then
emeventsproj eventset=$eventfilt rejectbadevents=Y evimageset=$evmap
embadpixfind evimageset=$evmap badpixset=$bad
if (lowenerbadpix) select PHA < 150 and run again incrementally
else
badpixfind eventset=$eventfilt thresholdlabel=rate \
badpixset=$bad \
hithresh=0.005 narrowerthanpsf=3.0 backgroundrate=1.E-5
endif
end loop over CCDs and nodes
if stopafterbadpixfind stop
end subroutine badpixLoop
subroutine mergeEvents
imerge = 'T' // core // 'MIEVLM0000.FIT'
tmerge = 'T' // core // 'TIEVLM0000.FIT'
evlistcomb eventsets='T'//core//'CAEVLI00*.FIT' imagingset=$imerge \
timingset=$tmerge maintable='EVENTS OFFSETS'
if fulloutput then
emosimgcolnames="TIME RAWX RAWY DETX DETY X Y PHA PI FLAG PATTERN
FRAME ENERGYE1 ENERGYE2 ENERGYE3 ENERGYE4 PERIPIX OFFSETX OFFSETY"
emosimgcoltypes="double int16 int16 int16 int16 int32 int32 int16
int16 int32 int8 int32 int16 int16 int16 int16 int8 int16 int16"
endif
if applyccdgti then
Loop over 'T'//core//'LOCGTI00*.FIT' files
expr = expr // '|| (CCDNR==' // nccd // ' && GTI($gtiout,TIME))'
endif
eventim = 'P' // core // 'MIEVLI0000.FIT'
evselect table=$imerge filteredset=$eventim \
expression=$expr destruct=Y keepfilteroutput=Y
fparkey "EPIC MOS IMAGING MODE EVENT LIST" $eventim[0] CONTENT \
add=Y insert=DATE"
fappend $sasccf[CALINDEX] $eventim
if ($tmerge exists) then
eventti = 'P' // core // 'TIEVLI00000.FIT'
evselect table=$tmerge filteredset=$eventti \
expression=$expr destruct=Y keepfilteroutput=Y
fparkey "EPIC TIMING MODE EVENT LIST" $eventti[0] CONTENT \
add=Y insert=DATE"
fappend $sasccf[CALINDEX] $eventti
endif
end subroutine mergeEvents
subroutine makeFlareTs
expr = "(PATTERN==0) && ((FLAG & 0x762b8000) == 0) && #XMMEA_22"
flarets = 'P' // core // 'FBKTSR0000.FIT'
check that expected counts per bin in quiet conditions is > 10,
otherwise increase $flaretimebin
evselect table=$eventim expression=$expr updateexposure=N \
rateset=$flarets timebinsize=$flaretimebin \
timecolumn=TIME maketimecolumn=Y makeratecolumn=Y
add FRACEXP column (currently done by looking at full timeseries)
divide by CCD area (IN_FOV keyword) and FRACEXP
end subroutine makeFlareTs
subroutine mergeTs
globts = 'P' // obsid // 'EMX000FBKTSR0000.FIT'
if $globts exists then
multiply by CCD area and FRACEXP
merge columns of $flarets and $globts:
RATE = RATE1 + RATE2
ERROR = SQRT(ERROR1**2 + ERROR2**2)
FRACEXP = FRACEXP1 + FRACEXP2
divide by CCD area and FRACEXP
endif else then
cp $flarets $globts
endelse
end subroutine mergeTs
subroutine tsToGTI
gtiflare = timeseries prefix // 'FBKGTI0000.FIT'
tabgtigen table=$flarets expression="RATE<$flaremaxrate" \
gtiset=$gtiflare
evselect table=$gtiflare writedss=N updateexposure=N keepfilteroutput=Y \
expression="(STOP - START) > 1.5*$flaretimebin"
end subroutine tsToGTI
subroutine applyFlareGTI
expr = "GTI($gtiflare,TIME)"
evselect table=$eventim destruct=Y keepfilteroutput=Y expression=$expr
evselect table=$eventti destruct=Y keepfilteroutput=Y expression=$expr
end subroutine applyFlareGTI
XMM-Newton SOC -- 2025-01-27