예제 #1
0
def main():
    pr = cProfile.Profile()
    pr.enable()

    rng = galsim.UniformDeviate(8675309)

    wcs = galsim.FitsWCS('../tests/des_data/DECam_00154912_12_header.fits')
    image = galsim.Image(xsize, ysize, wcs=wcs)
    bandpass = galsim.Bandpass('LSST_r.dat', wave_type='nm').thin(0.1)
    base_wavelength = bandpass.effective_wavelength

    angles = galsim.FRatioAngles(fratio, obscuration, rng)
    sensor = galsim.SiliconSensor(rng=rng, nrecalc=nrecalc)

    # Figure out the local_sidereal time from the observation location and time.
    lsst_lat = '-30:14:23.76'
    lsst_long = '-70:44:34.67'
    obs_time = '2012-11-24 03:37:25.023964'  # From the header of the wcs file

    obs = astropy.time.Time(obs_time, scale='utc', location=(lsst_long + 'd', lsst_lat + 'd'))
    local_sidereal_time = obs.sidereal_time('apparent').value

    # Convert the ones we need below to galsim Angles.
    local_sidereal_time *= galsim.hours
    lsst_lat = galsim.Angle.from_dms(lsst_lat)

    times = []
    mem = []
    phot = []

    t0 = time.clock()
    for iobj in range(nobjects):
        sys.stderr.write('.')
        psf = make_psf(rng)
        gal = make_gal(rng)
        obj = galsim.Convolve(psf, gal)

        sed = get_sed(rng)
        waves = galsim.WavelengthSampler(sed=sed, bandpass=bandpass, rng=rng)

        image_pos = get_pos(rng)
        sky_coord = wcs.toWorld(image_pos)
        bounds, offset = calculate_bounds(obj, image_pos, image)

        ha = local_sidereal_time - sky_coord.ra
        dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                               obj_coord=sky_coord, HA=ha, latitude=lsst_lat)

        surface_ops = (waves, angles, dcr)

        obj.drawImage(method='phot', image=image[bounds], offset=offset,
                      rng=rng, sensor=sensor,
                      surface_ops=surface_ops)

        times.append(time.clock() - t0)
        mem.append(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
        phot.append(obj.flux)

    image.write('phot.fits')
    phot = np.cumsum(phot)
    make_plots(times, mem, phot)

    pr.disable()
    ps = pstats.Stats(pr).sort_stats('time')
    ps.print_stats(20)
예제 #2
0
def test_dcr():
    """Test the dcr surface op
    """
    # This tests that implementing DCR with the surface op is equivalent to using
    # ChromaticAtmosphere.
    # We use fairly extreme choices for the parameters to make the comparison easier, so
    # we can still get good discrimination of any errors with only 10^6 photons.
    zenith_angle = 45 * galsim.degrees  # Larger angle has larger DCR.
    parallactic_angle = 129 * galsim.degrees  # Something random, not near 0 or 180
    pixel_scale = 0.03  # Small pixel scale means shifts are many pixels, rather than a fraction.
    alpha = -1.2  # The normal alpha is -0.2, so this is exaggerates the effect.

    bandpass = galsim.Bandpass('LSST_r.dat', 'nm')
    base_wavelength = bandpass.effective_wavelength
    base_wavelength += 500  # This exaggerates the effects fairly substantially.

    sed = galsim.SED('CWW_E_ext.sed', wave_type='ang', flux_type='flambda')

    flux = 1.e6
    base_PSF = galsim.Kolmogorov(fwhm=0.3)

    # Use ChromaticAtmosphere
    im1 = galsim.ImageD(50, 50, scale=pixel_scale)
    star = galsim.DeltaFunction() * sed
    star = star.withFlux(flux, bandpass=bandpass)
    chrom_PSF = galsim.ChromaticAtmosphere(base_PSF,
                                           base_wavelength=base_wavelength,
                                           zenith_angle=zenith_angle,
                                           parallactic_angle=parallactic_angle,
                                           alpha=alpha)
    chrom = galsim.Convolve(star, chrom_PSF)
    chrom.drawImage(bandpass, image=im1)

    # Use PhotonDCR
    im2 = galsim.ImageD(50, 50, scale=pixel_scale)
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           zenith_angle=zenith_angle,
                           parallactic_angle=parallactic_angle,
                           alpha=alpha)
    achrom = base_PSF.withFlux(flux)
    rng = galsim.BaseDeviate(31415)
    wave_sampler = galsim.WavelengthSampler(sed, bandpass, rng)
    surface_ops = [wave_sampler, dcr]
    achrom.drawImage(image=im2,
                     method='phot',
                     rng=rng,
                     surface_ops=surface_ops)

    im1 /= flux  # Divide by flux, so comparison is on a relative basis.
    im2 /= flux
    printval(im2, im1, show=False)
    np.testing.assert_almost_equal(
        im2.array,
        im1.array,
        decimal=4,
        err_msg="PhotonDCR didn't match ChromaticAtmosphere")

    # Repeat with thinned bandpass and SED to check that thin still works well.
    im3 = galsim.ImageD(50, 50, scale=pixel_scale)
    thin = 0.1  # Even higher also works.  But this is probably enough.
    thin_bandpass = bandpass.thin(thin)
    thin_sed = sed.thin(thin)
    print('len bp = %d => %d' %
          (len(bandpass.wave_list), len(thin_bandpass.wave_list)))
    print('len sed = %d => %d' % (len(sed.wave_list), len(thin_sed.wave_list)))
    wave_sampler = galsim.WavelengthSampler(thin_sed, thin_bandpass, rng)
    achrom.drawImage(image=im3,
                     method='phot',
                     rng=rng,
                     surface_ops=surface_ops)

    im3 /= flux
    printval(im3, im1, show=False)
    np.testing.assert_almost_equal(
        im3.array,
        im1.array,
        decimal=4,
        err_msg="thinning factor %f led to 1.e-4 level inaccuracy" % thin)

    # Check scale_unit
    im4 = galsim.ImageD(50, 50, scale=pixel_scale / 60)
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           zenith_angle=zenith_angle,
                           parallactic_angle=parallactic_angle,
                           scale_unit='arcmin',
                           alpha=alpha)
    surface_ops = [wave_sampler, dcr]
    achrom.dilate(1. / 60).drawImage(image=im4,
                                     method='phot',
                                     rng=rng,
                                     surface_ops=surface_ops)
    im4 /= flux
    printval(im4, im1, show=False)
    np.testing.assert_almost_equal(
        im4.array,
        im1.array,
        decimal=4,
        err_msg="PhotonDCR with scale_unit=arcmin, didn't match")

    # Check some other valid options
    # alpha = 0 means don't do any size scaling.
    # obj_coord, HA and latitude are another option for setting the angles
    # pressure, temp, and water pressure are settable.
    # Also use a non-trivial WCS.
    wcs = galsim.FitsWCS('des_data/DECam_00154912_12_header.fits')
    image = galsim.Image(50, 50, wcs=wcs)
    bandpass = galsim.Bandpass('LSST_r.dat', wave_type='nm').thin(0.1)
    base_wavelength = bandpass.effective_wavelength
    lsst_lat = galsim.Angle.from_dms('-30:14:23.76')
    lsst_long = galsim.Angle.from_dms('-70:44:34.67')
    local_sidereal_time = 3.14 * galsim.hours  # Not pi. This is the time for this observation.

    im5 = galsim.ImageD(50, 50, wcs=wcs)
    obj_coord = wcs.toWorld(im5.true_center)
    base_PSF = galsim.Kolmogorov(fwhm=0.9)
    achrom = base_PSF.withFlux(flux)
    dcr = galsim.PhotonDCR(
        base_wavelength=bandpass.effective_wavelength,
        obj_coord=obj_coord,
        HA=local_sidereal_time - obj_coord.ra,
        latitude=lsst_lat,
        pressure=72,  # default is 69.328
        temperature=290,  # default is 293.15
        H2O_pressure=0.9)  # default is 1.067
    #alpha=0)            # default is 0, so don't need to set it.
    surface_ops = [wave_sampler, dcr]
    achrom.drawImage(image=im5,
                     method='phot',
                     rng=rng,
                     surface_ops=surface_ops)

    im6 = galsim.ImageD(50, 50, wcs=wcs)
    star = galsim.DeltaFunction() * sed
    star = star.withFlux(flux, bandpass=bandpass)
    chrom_PSF = galsim.ChromaticAtmosphere(
        base_PSF,
        base_wavelength=bandpass.effective_wavelength,
        obj_coord=obj_coord,
        HA=local_sidereal_time - obj_coord.ra,
        latitude=lsst_lat,
        pressure=72,
        temperature=290,
        H2O_pressure=0.9,
        alpha=0)
    chrom = galsim.Convolve(star, chrom_PSF)
    chrom.drawImage(bandpass, image=im6)

    im5 /= flux  # Divide by flux, so comparison is on a relative basis.
    im6 /= flux
    printval(im5, im6, show=False)
    np.testing.assert_almost_equal(
        im5.array,
        im6.array,
        decimal=3,
        err_msg="PhotonDCR with alpha=0 didn't match")

    # Also check invalid parameters
    zenith_coord = galsim.CelestialCoord(13.54 * galsim.hours, lsst_lat)
    assert_raises(
        TypeError,
        galsim.PhotonDCR,
        zenith_angle=zenith_angle,
        parallactic_angle=parallactic_angle)  # base_wavelength is required
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  base_wavelength=500,
                  parallactic_angle=parallactic_angle
                  )  # zenith_angle (somehow) is required
    assert_raises(
        TypeError,
        galsim.PhotonDCR,
        500,
        zenith_angle=34.4,
        parallactic_angle=parallactic_angle)  # zenith_angle must be Angle
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  zenith_angle=zenith_angle,
                  parallactic_angle=34.5)  # parallactic_angle must be Angle
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  latitude=lsst_lat)  # Missing HA
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  HA=local_sidereal_time - obj_coord.ra)  # Missing latitude
    assert_raises(TypeError, galsim.PhotonDCR, 500,
                  obj_coord=obj_coord)  # Need either zenith_coord, or (HA,lat)
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  zenith_coord=zenith_coord,
                  HA=local_sidereal_time -
                  obj_coord.ra)  # Can't have both HA and zenith_coord
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  zenith_coord=zenith_coord,
                  latitude=lsst_lat)  # Can't have both lat and zenith_coord
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  zenith_angle=zenith_angle,
                  parallactic_angle=parallactic_angle,
                  H20_pressure=1.)  # invalid (misspelled)
    assert_raises(ValueError,
                  galsim.PhotonDCR,
                  500,
                  zenith_angle=zenith_angle,
                  parallactic_angle=parallactic_angle,
                  scale_unit='inches')  # invalid scale_unit

    # Invalid to use dcr without some way of setting wavelengths.
    assert_raises(galsim.GalSimError,
                  achrom.drawImage,
                  im2,
                  method='phot',
                  surface_ops=[dcr])
예제 #3
0
def test_dcr_moments():
    """Check that DCR gets the direction of the moment changes correct for some simple geometries.
    i.e. Basically check the sign conventions used in the DCR code.
    """
    # First, the basics.
    # 1. DCR shifts blue photons closer to zenith, because the index of refraction larger.
    #    cf. http://lsstdesc.github.io/chroma/
    # 2. Galsim models profiles as seen from Earth with North up (and therefore East left).
    # 3. Hour angle is negative when the object is in the east (soon after rising, say),
    #    zero when crossing the zenith meridian, and then positive to the west.

    # Use g-band, where the effect is more dramatic across the band than in redder bands.
    # Also use a reference wavelength significantly to the red, so there should be a net
    # overall shift towards zenith as well as a shear along the line to zenith.
    bandpass = galsim.Bandpass('LSST_g.dat', 'nm').thin(0.1)
    base_wavelength = 600  # > red end of g band

    # Uniform across the band is fine for this.
    sed = galsim.SED('1', wave_type='nm', flux_type='fphotons')
    rng = galsim.BaseDeviate(31415)
    wave_sampler = galsim.WavelengthSampler(sed, bandpass, rng)

    star = galsim.Kolmogorov(fwhm=0.3,
                             flux=1.e6)  # 10^6 photons should be enough.
    im = galsim.ImageD(
        50, 50, scale=0.05)  # Small pixel scale, so shift is many pixels.
    ra = 0 * galsim.degrees  # Completely irrelevant here.
    lat = -20 * galsim.degrees  # Also doesn't really matter much.

    # 1. HA < 0, Dec < lat  Spot should be shifted up and right.  e2 > 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=-2 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(
                               ra, lat - 20 * galsim.degrees))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('1. HA < 0, Dec < lat: ', moments)
    assert moments['My'] > 0  # up
    assert moments['Mx'] > 0  # right
    assert moments['Mxy'] > 0  # e2 > 0

    # 2. HA = 0, Dec < lat  Spot should be shifted up.  e1 < 0, e2 ~= 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=0 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(
                               ra, lat - 20 * galsim.degrees))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('2. HA = 0, Dec < lat: ', moments)
    assert moments['My'] > 0  # up
    assert abs(moments['Mx']) < 0.05  # not left or right
    assert moments['Mxx'] < moments['Myy']  # e1 < 0
    assert abs(moments['Mxy']) < 0.1  # e2 ~= 0

    # 3. HA > 0, Dec < lat  Spot should be shifted up and left.  e2 < 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=2 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(
                               ra, lat - 20 * galsim.degrees))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('3. HA > 0, Dec < lat: ', moments)
    assert moments['My'] > 0  # up
    assert moments['Mx'] < 0  # left
    assert moments['Mxy'] < 0  # e2 < 0

    # 4. HA < 0, Dec = lat  Spot should be shifted right.  e1 > 0, e2 ~= 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=-2 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(ra, lat))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('4. HA < 0, Dec = lat: ', moments)
    assert abs(moments['My']
               ) < 1.  # not up or down  (Actually slightly down in the south.)
    assert moments['Mx'] > 0  # right
    assert moments['Mxx'] > moments['Myy']  # e1 > 0
    assert abs(
        moments['Mxy']
    ) < 2.  # e2 ~= 0  (Actually slightly negative because of curvature.)

    # 5. HA = 0, Dec = lat  Spot should not be shifted.  e1 ~= 0, e2 ~= 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=0 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(ra, lat))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('5. HA = 0, Dec = lat: ', moments)
    assert abs(moments['My']) < 0.05  # not up or down
    assert abs(moments['Mx']) < 0.05  # not left or right
    assert abs(moments['Mxx'] - moments['Myy']) < 0.1  # e1 ~= 0
    assert abs(moments['Mxy']) < 0.1  # e2 ~= 0

    # 6. HA > 0, Dec = lat  Spot should be shifted left.  e1 > 0, e2 ~= 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=2 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(ra, lat))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('6. HA > 0, Dec = lat: ', moments)
    assert abs(moments['My']
               ) < 1.  # not up or down  (Actually slightly down in the south.)
    assert moments['Mx'] < 0  # left
    assert moments['Mxx'] > moments['Myy']  # e1 > 0
    assert abs(
        moments['Mxy']
    ) < 2.  # e2 ~= 0  (Actually slgihtly positive because of curvature.)

    # 7. HA < 0, Dec > lat  Spot should be shifted down and right.  e2 < 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=-2 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(
                               ra, lat + 20 * galsim.degrees))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('7. HA < 0, Dec > lat: ', moments)
    assert moments['My'] < 0  # down
    assert moments['Mx'] > 0  # right
    assert moments['Mxy'] < 0  # e2 < 0

    # 8. HA = 0, Dec > lat  Spot should be shifted down.  e1 < 0, e2 ~= 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=0 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(
                               ra, lat + 20 * galsim.degrees))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('8. HA = 0, Dec > lat: ', moments)
    assert moments['My'] < 0  # down
    assert abs(moments['Mx']) < 0.05  # not left or right
    assert moments['Mxx'] < moments['Myy']  # e1 < 0
    assert abs(moments['Mxy']) < 0.1  # e2 ~= 0

    # 9. HA > 0, Dec > lat  Spot should be shifted down and left.  e2 > 0.
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           HA=2 * galsim.hours,
                           latitude=lat,
                           obj_coord=galsim.CelestialCoord(
                               ra, lat + 20 * galsim.degrees))
    surface_ops = [wave_sampler, dcr]
    star.drawImage(image=im, method='phot', rng=rng, surface_ops=surface_ops)
    moments = galsim.utilities.unweighted_moments(im, origin=im.true_center)
    print('9. HA > 0, Dec > lat: ', moments)
    assert moments['My'] < 0  # down
    assert moments['Mx'] < 0  # left
    assert moments['Mxy'] > 0  # e2 > 0
    def drawObject(self, gsObject):
        """
        Draw an astronomical object on all of the relevant FITS files.

        @param [in] gsObject is an instantiation of the GalSimCelestialObject
        class carrying all of the information for the object whose image
        is to be drawn

        @param [out] outputString is a string denoting which detectors the astronomical
        object illumines, suitable for output in the GalSim InstanceCatalog
        """

        # find the detectors which the astronomical object illumines
        outputString, \
        detectorList, \
        centeredObj = self.findAllDetectors(gsObject)

        # Make sure this object is marked as "drawn" since we only
        # care that this method has been called for this object.
        self.drawn_objects.add(gsObject.uniqueId)

        # Compute the realized object fluxes (as drawn from the
        # corresponding Poisson distribution) for each band and return
        # right away if all values are zero in order to save compute.
        fluxes = [gsObject.flux(bandpassName) for bandpassName in self.bandpassDict]
        realized_fluxes = [galsim.PoissonDeviate(self._rng, mean=f)() for f in fluxes]
        if all([f == 0 for f in realized_fluxes]):
            return outputString

        if len(detectorList) == 0:
            # there is nothing to draw
            return outputString

        self._addNoiseAndBackground(detectorList)

        # Create a surface operation to sample incident angles and a
        # galsim.SED object for sampling the wavelengths of the
        # incident photons.
        fratio = 1.234  # From https://www.lsst.org/scientists/keynumbers
        obscuration = 0.606  # (8.4**2 - 6.68**2)**0.5 / 8.4
        angles = galsim.FRatioAngles(fratio, obscuration, self._rng)

        sed_lut = galsim.LookupTable(x=gsObject.sed.wavelen,
                                     f=gsObject.sed.flambda)
        gs_sed = galsim.SED(sed_lut, wave_type='nm', flux_type='flambda',
                            redshift=0.)

        local_hour_angle \
            = self.getHourAngle(self.obs_metadata.mjd.TAI,
                                self.obs_metadata.pointingRA)*galsim.degrees
        obs_latitude = self.observatory.getLatitude().asDegrees()*galsim.degrees
        ra_obs, dec_obs = observedFromPupilCoords(gsObject.xPupilRadians,
                                                  gsObject.yPupilRadians,
                                                  obs_metadata=self.obs_metadata)
        obj_coord = galsim.CelestialCoord(ra_obs*galsim.degrees,
                                          dec_obs*galsim.degrees)
        for bandpassName, realized_flux in zip(self.bandpassDict, realized_fluxes):
            gs_bandpass = self.gs_bandpass_dict[bandpassName]
            waves = galsim.WavelengthSampler(sed=gs_sed, bandpass=gs_bandpass,
                                             rng=self._rng)
            dcr = galsim.PhotonDCR(base_wavelength=gs_bandpass.effective_wavelength,
                                   HA=local_hour_angle,
                                   latitude=obs_latitude,
                                   obj_coord=obj_coord)

            # Set the object flux to the value realized from the
            # Poisson distribution.
            obj = centeredObj.withFlux(realized_flux)

            for detector in detectorList:

                name = self._getFileName(detector=detector,
                                         bandpassName=bandpassName)

                xPix, yPix = detector.camera_wrapper\
                   .pixelCoordsFromPupilCoords(gsObject.xPupilRadians,
                                               gsObject.yPupilRadians,
                                               chipName=detector.name,
                                               obs_metadata=self.obs_metadata)

                # Ensure the rng used by the sensor object is set to the desired state.
                self.sensor[detector.name].rng.reset(self._rng)
                surface_ops = [waves, dcr, angles]

                # Desired position to draw the object.
                image_pos = galsim.PositionD(xPix, yPix)

                # Find a postage stamp region to draw onto.  Use (sky
                # noise)/3. as the nominal minimum surface brightness
                # for rendering an extended object.
                keep_sb_level = np.sqrt(self.sky_bg_per_pixel)/3.
                bounds = self.getStampBounds(gsObject, realized_flux, image_pos,
                                             keep_sb_level, 3*keep_sb_level)

                # Ensure the bounds of the postage stamp lie within the image.
                bounds = bounds & self.detectorImages[name].bounds

                if bounds.isDefined():
                    # offset is relative to the "true" center of the postage stamp.
                    offset = image_pos - bounds.true_center

                    obj.drawImage(method='phot',
                                  offset=offset,
                                  rng=self._rng,
                                  maxN=int(1e6),
                                  image=self.detectorImages[name][bounds],
                                  sensor=self.sensor[detector.name],
                                  surface_ops=surface_ops,
                                  add_to_image=True,
                                  poisson_flux=False,
                                  gain=detector.photParams.gain)

                    # If we are writing centroid files,store the entry.
                    if self.centroid_base_name is not None:
                        centroid_tuple = (detector.fileName, bandpassName, gsObject.uniqueId,
                                          gsObject.flux(bandpassName), xPix, yPix)
                        self.centroid_list.append(centroid_tuple)

        self.write_checkpoint()
        return outputString