Canadian Astronomy Data Centre
Herzberg Institute of Astrophysics
  ST-ECF
  ESA-ESO
CADC Homepage

The WFPC2 Association Project Version 2
Stacking algorithm

Association Example: a tale of the Chandra Deep Field

Single Exposure

Association Product

Please note that this page is in construction. More details will appear very soon

Pipeline details

The wfpc2 associations pipeline is divided in multiple tasks. They are:

  1. IMSTACK: Stacking the members of an association together

IMSTACK VERSION: 4.1

Introduction

The imstack process in 6 sentences:
  • Rescales all the input images to common gain, exposure time and common background sky level;
  • Shift all members to the same sky position, with the provision that imshift is not applied if the shift is lower than a given tolerance (set to be 0.15 pixels);
  • Runs the Skepticism Algorithm (P.Stetson, 1979) a first time to estimate a better weight map for a subsequent second run;
  • Runs the Skepticism Algorithm a second time to stack together the imshifted images, so to obtain:
    1. the FINAL stack, normalised at the AVERAGE of the exposure times
    2. the FINAL weight map
  • Computes, and stores in the header, all the Characterisation VO parameters, including coverage, sampling and resolution of the spatial, spectral and temporal axes;
  • Stores in the header all the used zeropoints (ZEROSTS,ZEROSTE,ZEROABS,ZEROABE).

The full description

The entire pystack.py is here described. It consists of the following sections:
  1. Initialisation;
  2. Prepare the weight maps
    1. Prepare a mask using the data quality (c1 extension) and the flat field information;
    2. Prepare a variance map for each of the input (member) images, taking into account:
      • photon noise
      • readout noise
      • dark contribution
      • flat fielding
    3. Obtain a weight map (of type variance) by multiplying the mask and the variance map;
  3. Scale the input science images to same gain, exposure time, and same sky level;
  4. Shift both science and weight images to common grid;
  5. Run the skepticism algorithm (pystack) a first time, to obtain a better guess of what each input image should have looked like;
  6. Scale back the obtained pystack science image to each original member level (gain, exptime, and sky level);
  7. Compute the better weight map for each member image, using the image obtained in the previous step, and reapplying the same method;
  8. Run the skepticism algorithm (pystack) again, with the new weight maps;
  9. Compute the Characterisation VO parameters, including coverage, sampling and resolution of the spatial, spectral and temporal axes (e.g. CVOSRES, CVOWSPA, etc.).

  1. INITIALISATION

    Some initialisation, of which worth noting are:

    • setting readnoise and gain for the four chips (see Table GAIN and READNOISE below)
    • setting the maximum shift tolerance to 0.15 pixels
      members shifted by less than shift_tolerance pixels are considered well aligned, and no imshift will occur.
    • computing the min and max of the x and y shifts among the members (from the .asn file)
    • checking whether the members have all the same gain or not (quot;mixed gain")
    • determining the nominal gain of the coadded output image (stack_image),to be:
      nominal gain = 14.0 if all members have ATODGAIN=15
      nominal gain = 7.0 in all other cases(all ATODGAIN=7, or mixed cases of 7 and 15).
    • computing the average exposure time




  2. PREPARE THE WEIGHT MAPS

    For each member, and for each chip:
    1. Prepare a mask to flag artifacts

      using the data quality (c1.fits extension) and the flat field information,
      (1 - good, 0 - bad):

      1. find which (inverse) flatfield was used from the member c0.fits file

      2. build a flatfield mask (MASKFFinv) from the original flatfield:
        set to val=1
        all pixels which exhibit an inverse flatfield lower than 2.
        set to val=0
        all bad pixels which exhibit an inverse flatfield greater than 2,
        to cope with the bad vignetting.

      3. build a flag mask from the c1.fits (MASKC1):
        set to val=1
        all the good pixels (where c1 pixel val is 0-good or 1024-corrected warmpixel)
        set to val=0
        all the bad pixels (where c1 pixel value is not 0 AND not 1024).

        MASKC1 = 1if C1 = 1024repaired warm pixel
        MASKC1 = 0if C1 other values but 0charge transfer traps, dead pixels, blocked columns, A/D convert saturation, unrepaired warm pixel, other questionable pixels
        MASKC1 = 1for C1 = 0good pixel

        For an explanation of the c1 pixel values, please refer to the WFPC2 Data Quality table.

      The mask that will be used will hence be:

      MASKmember,chip = MASKFFinv * MASKC1 (1)

    2. Prepare a variance map

      for each of the input (member) images;

      1. Variance of a C0 member file:
        1. Given an image in electrons, its variance can be computed using the following formula:
          (2)
          whereby the three addictive terms cover the noise contribution respectively of the poissonian photon noise, the read out noise, and the noise contribution of the dark current:
          C0e-
          stands for the actual member image values in electrons
          ge-/adu
          is the gain setting of the chip in electrons per adu
          RN
          the readout noise of the given chip
          Pdark(T)
          is the number of electrons expected per pixel and per second,
          which depends on the temperature (T) of the detector (see below)
          t + 46
          is the total time during which the dark current accumulated,
          as per the WFPC2 Instrument Handbook Exposure Time Calculator paragraph.

        2. The science image is usually expressed in counts (adu) and not in electrons:

          (3)

          where

          C0adu
          stands for the actual member image pixel values in adu
          FFinv
          stands for the inversed flat field pixel values

        3. Hence the variance image transforms similarly:

          (4)

        4. Applying both (3) and (4) to the equation (2) we obtain the final equation for the variance map in counts (adu):

          (5)

    3. Obtain a weigth map (of type variance) by multiplying the mask (1) and the variance map (5).

      Hence, the weight map which will be used for each member is expressed by the formula:

      WEIGHT_MAPmember,chip = MASKmember,chip * VARaduFFinv (6)

    4. Masking the weight map (setting it to 1.E20) and the mask (to zero) for the vignetted region of the chip

      MASKmember,chip = 0 if ( x < vignetted  or  y < vignetted )

      WEIGHT_MAPmember,chip = 1.E20 if ( x < vignetted  or  y < vignetted )

      (7)

      where the vignetted limits in X and Y vary with the chip number:

      From Table 1.2, p.10, WFPC2 Data Handbook v4.0, Jan 2002
      ChipX limitY limit
      14452
      24626
      33047
      44344




  3. Scale the input science images

    to same gain, exposure time, and same sky level

    Each member (subscript j) science data is rescaled to the same nominal gain ( gainstack ), and to the average exposure time ( avg_exptime ) of the association:

    Scaled_Imagej = Imagej * (gainj / gainstack) (avg_exptime/ exptimej)

    (9)




  4. Shift science, weight, flat and mask images

    Both the science image, and accompanying weight map, of each chip are shifted onto a common grid.
    At this stage we also shift the flat field and the mask images, since they will be needed for a second iteration.

    We use the imshift iraf task with linear interpolation for shift values > 0.15 pixels. That is, a lower shift is considered to be negligible.

    XXX PLEASE, TOMORROW CONTINUE FROM HERE XXX

  5. Stacking the images: iteration 1

    Datajs and Variancejs
    where Datajs = Dataj shifted

    Then we need to shift the MAPj and the Flatj into MAPjs and Flatjs

    Then we process these 2 input images lists with pystack and the result is
    a stack image with bad values masked to 10e06 called P1

    Processing Steps for WFPC2 V2: Pass two (for J images)

    It is essentially the same equation than above but the have first to "descale" the P1 image with the ration of gain and the ration of exposure time, i.e.: (gainj / gainstack) and (tm/ tj)

    The variance J2

    Variancej2 = [ (Flatjs * P1 / gainj ) * (tj/tm) * (gainstack / gainj ) + Flatjs2 * Rj2/ gainj2 ] * (gainj / gainstack) * (tm/ tj)* MAPjs

    The data J2 is simply

    Dataj2 = Datajs

    Then pystack pass 2

    The resulting stacked image and stack are composing the final product.

    Astrometric correction (using USNOB)

    Image caracterisation

    catalogue extraction

    Storage in AD


    Readout Noise Table

    Readout noises
    used by the imstack.py procedure
    Nominal Gain Readout Noise (electrons)
    chip 1 chip 2 chip 3 chip 4
    7 5.24 5.51 5.22 5.19
    15 7.02 7.84 6.99 8.32

    Gain Table

    Real Gain
    used by the imstack.py procedure
    Nominal Gain Real Gain
    chip 1 chip 2 chip 3 chip 4
    7 7.12 7.12 6.90 7.10
    15 13.99 14.50 13.95 13.95

    GAIN manipulation

    From Source extractor for dummies V4
    Method Effective Gain Magnitude zeropoint Input image
    1gain * total_exp_time Zeropoint(1 sec) Image in count/sec
    2gainZeropoint(1 sec) * log10(total_exp_time)Sum of N frames
    3N * gainZeropoint(1 sec) * log10(average_exp_time)Average of N frames
    42 * N * gain / 3Zeropoint(1 sec) * log10(average_exp_time)Median of N frames

    WFPC2 Data Quality Flag Values

    AS from the table 3.4 in WFPC2 Instrument Handbook
    Flag Value Description
    0 Good pixel
    1 Reed-Solomon decoding error. This pixel is part of a packet of data in which one or more pixels may have been corrupted during transmission.
    2 Calibration file defect-set if pixel flagged in any calibration file. Includes charge transfer traps identified in static pixel mask file (.r0h).
    4 Permanent camera defect. Static defects are maintained in the CDBS database and flag problems such as blocked columns and dead pixels. (Not currently used.)
    8 A/D converter saturation. The actual signal is unrecoverable but known to exceed the A/D full-scale signal (4095).1
    16 Missing data. The pixel was lost during readout or transmission. (Not currently used.)
    32 Bad pixel that does not fall into above categories.
    128 Permanent charge trap. (Not currently used.)
    256 Questionable pixel. A pixel lying above a charge trap which may be affected by the trap.
    512 Unrepaired warm pixel.
    1024 Repaired warm pixel.

    Estimate of Dark Current contribution to the noise

    From WFPC2 Instrument book c14/15, page 88, the dark count rate in electrons per second per pixel is tabularised as follows:

    Temperature Dark counts
    (electrons/second/pixel)
    -20 10
    -30 3.
    -40 1.
    -50 0.3
    -70 0.03
    -77 0.016
    -83 0.008
    -88 0.0045

    The detector temperature is provided by the FITS keywords: UCH1CJTM, UCH2CJTM, UCH3CJTM, UCH4CJTM for each of the four chips.

    Interpolation is required, and for that we use the following formula which approximates quite well the above table:

    Pdark = (273 + T) * 10^( 0.04719*T - 0.4592 )


    Magnitude systems

    STMAG

    ZEROPTsecond = -2.5 * log10(PHOTFLAM) + PHOTZPT
    ZEROPTexptime = -2.5 * log10(PHOTFLAM) + PHOTZPT + 2.5 * log10(exptime)

    PHOTZPT = -21.1 (always)
    mstmag = -2.5 * log10(counts/exptime) + ZEROPTexptime
    mstmag = -2.5 * log10(counts/sec) + ZEROPTseconds
    mstmag = -2.5 * log10( PHOTFLAM * DN / EXPTIME) + PHOTZPT

    AB mag

    mAB = -2.5 log10( Fluxnu ) - 48.594
    where fluxnu is in ergs cm-2 s-1 HZ-1
    mAB = -2.5 log10( Fluxlambda ) - 2.402 - 5.0 * log10( lambda )
    where fluxlambda is in ergs cm-2 s-1 A-1
    and lambda in A
    Fnu = flambda * lambda2 / c

    flam = 3x10^18 * fnu / lam^2
    fnu = (lam^2 * flam) / 3x10^18

    Converting an image to flux

    flux = DN * PHOTFLAM / exposure_time
    where flux is in erg cm-2s-1A-1


    flux = DN * PHOTFLAM / exposure_time * PHOTPLAM**2 / 2.9972E18 * 1E+23
    where flux is in Jy

    JANSKY

    1 Jy = 1.0 * 10-26 (W/m2/Hz) = 1.0E-23 erg/s/cm2/Hz

    FWHM

            seeing_fwhm = 1.22 * (photplam / 24000000000.0 ) * 206264.806247
    	seeing_fwhm = math.sqrt( (seeing_fwhm * seeing_fwhm) + (pixscale[chip] * pixscale[chip])  )
    	24000000000.0 = size of the mirror
    	206264.806247 = 180 * 3600. / pi
    
    
            $diameter=2.4e10; #diameter of the telescope
    $arc_rad = 206264.8; #number of arcsec/rad
    $rayleigh=1.22*$photplam * $arc_rad / $diameter; #1.22 * lambda/D
    $resolution = sqrt( ($rayleigh**2) + ($pixscale**2))

    CVORES

    cvosres = (( photplam / 10.0E10 ) / 2.4 ) * (2.063 * (10**5)) cvonyqr = cvosres / pixscale[chip] cvosres = cvosres / 3600.0 The Nyquist ratio (spatial_resolution/spatial_sample). Values less than 2.5 are undersampled.

    equations

    # [Y ABnu] = -2.5 * log([X ergs/cm^2/s/Hz]) - 48.594
    # [Y ABnu] = -2.5 * log([X ergs/cm^2/s/A]) - 2.402 - 5.0 * log(lambda A)
    # [Y ABnu] = -2.5 * log([X W/m^2/Hz]) - 56.094
    # [Y ABnu] = -2.5 * log([X photon/cm^2/s/A]) + 16.852 - 2.5 * log(lambda A)
    # [Y ABnu] = -2.5 * log([X photon/cm^2/s/um]) + 16.852 - 2.5 * log(lambda um)
    [Y Jy] = 1.0E+23 * [X erg/cm^2/s/Hz]

    Daniel Durand, April 2004


    Alberto Micol, September 2004

    Photometric systems: zeropoints and formulae

    
    Generic: m = -2.5 * log10( DN/EXPTIME ) + ZEROPOINT
    
    ST sys:  mst = -2.5 * log10( Flambda ) - 21.10
    
    AB sys:  mAB = -2.5 * log10( Fnu ) - 48.60
    
    where Flambda is in erg/cm2/sec/A
      and Fnu        in erg/cm2/sec/Hz
    
    Flambda = countRate * PHOTFLAM
    
    Fnu     = Flambda * lambda2 / c
                       = countRate * PHOTFLAM * PHOTPLAM2 / c
    
    where:
    
     - counteRate is the number of counts diveded by the exptime
    
     - PHOTFLAM is the flux of a source with constant flux per unit wavelength
                (in erg/cm2/sec/A) which produces a count rate of 1DN/sec.
       Note: Obviously a change of GAIN will have repercussions on PHOTFLAM
    
     - c must be given in A/sec, that is: 2.99792E+18 A/sec
         since PHOTPLAM is in A, and PHOTFLAM in erg/cm2/sec/A.
    
    Hence,
    
     mst = -2.5 * log10( countRate * PHOTFLAM ) - 21.10
         = -2.5 * log10( countRate ) -2.5*log10( PHOTFLAM ) - 21.10
    
         = -2.5 * log10( count ) -2.5*log10( PHOTFLAM ) - 21.10 + 2.5 * log10( EXPTIME )
    
    
     mAB = -2.5 * log10( countRate * PHOTFLAM * PHOTPLAM2 / c ) - 48.60
         = -2.5 * log10( countRate ) -2.5*log10(PHOTFLAM*PHOTPLAM2/c) - 48.60
    
         = -2.5 * log10( count ) -2.5*log10(PHOTFLAM*PHOTPLAM2/c) - 48.60 + 2.5*log10( EXPTIME )
    
     
    

    Effective Gain

    The effective gain is to be used within PIPE only when running SExtractor,
    that is, when the noise of the image must be computed.
    
    The effective gain is g for the noise of an single image.
    
    The effective gain is g for the noise of an coadded image (pure sum).
    
    The effective gain is N * g for the noise of an averaged image.
    
       That's because the poissonian noise can be computed only from the Total number of electrons,
    not from the average number of electrons; and the total number of electrons is N * g * the number of counts
    of an averaged image. All the formulae to do with gain
    FLUX COMPUTATION
    
    For a source which has 1DN/sec in an image with gain g,
    the flux is PHOTFLAM, where PHOTFLAM is to be scaled to g7 or g15.
    
    Flux(erg/cm2/sec/A) = NDN/exptime * PHOTFLAM(g=g7 or g15)
    
    For an averaged image, whose members are images at g=g7,
    the flux is computed this way:
    
    Flux = Total Ne / g7 / Total Exptime * PHOTFLAM(g7)
    
         = N * g7 * Mp / g7 / Total Exptime * PHOTFLAM(g7)
    
         = N/Total Exptime * Mp * PHOTFLAM(g7)
    
         = Mp / AVGExpTime * PHOTFLAM(g7)
    
    
    For a summed image, whose members are images at g=g7,
    the flux is computed this way:
    
    Flux = Total Ne / g7 / Total Exptime * PHOTFLAM(g7)
    
         = g7 * Tp / g7 / Total Exptime * PHOTFLAM(g7)
    
         =  Tp / Total Exptime * PHOTFLAM(g7)
    
    
    SExtractor outputs always FLUXes as counts;
    hence,
    a SExtractor run onto an averaged image, will return the average counts;
    a SExtractor run on a total image will return the total number of counts.
    
    
    -->
NRC HST