The following three fragments of pseudo-code summarize the computation of the spectrum at any given channel. fg and bg refer to source and background respectively, though these qualifiers are omitted where it may be understood that a TOTAL spectrum refers to fg and a BKG spectrum refers to bg. The first fragment is the formula for histogramming the events.
IF ( mode == HTR ) IF ( XDSP_CHANNEL in SpatialSourceRegion ) IF ( PI in EnergySourceRegion ) ++fg.counts IF ( PI in EnergyBackgroundRegion ) ++bg.counts ELSE IF ( PI in EnergySourceRegion ) IF ( XDSP_CHANNEL in SpatialSourceRegion ) ++fg.counts IF ( XDSP_CHANNEL in SpatialBackgroundRegion ) ++bg.counts
The next fragment computes the backscal and frac_exp statistics from the accumulated exposure, which is just the sum over all exposure map pixels that lie within the spatial selection region at the given channel. The fullExposure statistic is simply the DATAMAX attribute of the exposure map associated with the channel. Note that this association is not guaranteed to be unique (particularly at the trans-node boundary), and when the fullExposure value for a channel is not well defined the statistics are flagged as having been corrupted. If the exposure map was calculated in lambda space, this DATAMAX uncertainity is not longer applied.
IF ( mode == HTR ) fg.backscal = background distribution integrated over EnergySourceRegion bg.backscal = background distribution integrated over EnergyBackgroundRegion normalizer = $rebin * extent( SpatialSourceRegion ) * fullExposure frac_exp = normalizer ? fg.exposure / normalizer : 0 ELSE backscal = fullExposure ? exposure / fullExposure : 0 normalizer = $rebin * extent( SpatialRegion ) * fullExposure frac_exp = normalizer ? exposure / normalizer : 0
The last fragment shows how each output column is defined. The dubious flag indicates corrupted statistics as explained above, and it is also set in accordance with the edgechannels parameter.
AREASCAL = fullExposure / EXPOSURE QUALITY = dubious ? $badquality : 0 IF ( HDUCLAS2 == NET ) scale = bg.backscal ? fg.backscal / bg.backscal : 0 COUNTS = fg.counts - round( scale * bg.counts ) STAT_ERR = max( 1, sqrt( fg.counts + scale * scale * bg.counts ) ) FRAC_EXP = fg.frac_exp IF ( !bg.backscal OR fg.frac_exp < $exposed OR bg.frac_exp < $exposed ) QUALITY = $badquality ELSE COUNTS = counts BACKSCAL = backscal FRAC_EXP = frac_exp IF ( frac_exp < $exposed ) QUALITY = $badquality
XMM-Newton SOC -- 2021-11-30