Beispiel #1
0
    def buildWCS(self, config, base):
        """Build a local WCS from the given location in a DES focal plane, given a directory
        with the image files.  By default, it will pick a random chipnum and image position,
        but these can be optionally specified.
        """

        req = {
            "dir":
            str,  # The directory with the files. We'll use 'des_data' here.
            "root":
            str,  # The root name of the files. We'll use 'DECam_00154912' here.
        }
        opt = {
            "chipnum":
            int,  # Which chip to use: 1-62.  Default is to pick a random chip.
            "image_pos":
            galsim.PositionD,  # The position in the chip.  Default is random.
            "ext": str,  # The file extension.  Default is ".fits.fz"
            "bad_ccds":
            list,  # A list of ccds to skip.  Default is default_bad_ccds.
        }
        params, safe = galsim.config.GetAllParams(config,
                                                  base,
                                                  req=req,
                                                  opt=opt)

        # These will already have been checked to be present, since they are in the req dict.
        dir = params['dir']
        root = params['root']

        rng = base['rng']
        ud = galsim.UniformDeviate(
            rng)  # Will give float values between 0 and 1.

        if 'chipnum' in params:
            chipnum = params['chipnum']
        else:
            bad_ccds = params.get('bad_ccds', default_bad_ccds)
            chipnum = get_random_chipnum(ud, bad_ccds)

        ext = params.get('ext', '.fits.fz')

        # Build the full path of the file to use.
        file_name = os.path.join(dir, "%s_%02d%s" % (root, chipnum, ext))

        # Read the full WCS as a regular FitsWCS.
        full_wcs = galsim.FitsWCS(file_name)

        # Determine where in the image we will get the local WCS
        if 'image_pos' in params:
            image_pos = params['image_pos']
        else:
            x = ud(
            ) * 2048. + 0.5  # The pixel centers go from 1-2048, so edges are 0.5-2048.5
            y = ud() * 4096. + 0.5
            image_pos = galsim.PositionD(x, y)

        # Finally, return the local wcs at this location.
        local_wcs = full_wcs.local(image_pos)
        return local_wcs
Beispiel #2
0
 def __init__(self, dir, root, ext='.fits.fz'):
     # Read all the wcs objects indexed by their chipnum
     self.all_wcs = {}
     for chipnum in range(1, 63):
         file_name = os.path.join(dir, "%s_%02d%s" % (root, chipnum, ext))
         wcs = galsim.FitsWCS(file_name)
         self.all_wcs[chipnum] = wcs
Beispiel #3
0
 def __init__(self, dir, root, ext='.fits.fz', bad_ccds=default_bad_ccds):
     self.bad_ccds = bad_ccds
     # Read all the wcs objects indexed by their chipnum
     self.all_wcs = {}
     for chipnum in range(1,63):
         # skip bad ccds
         if chipnum not in bad_ccds:
             file_name = os.path.join(dir, "%s_%02d%s"%(root,chipnum,ext))
             wcs = galsim.FitsWCS(file_name)
             self.all_wcs[chipnum] = wcs
Beispiel #4
0
 def __init__(self, dir, root, ext='.fits.fz'):
     # Read all the wcs objects indexed by their chipnum
     self.all_wcs = {}
     for chipnum in range(1,63):
         file_name = os.path.join(dir, "%s_%02d%s"%(root,chipnum,ext))
         try:
             wcs = galsim.FitsWCS(file_name)
         except:
             continue
         self.all_wcs[chipnum] = wcs
     if len(self.all_wcs) == 0:
         raise RuntimeError("All input wcs files were missing or failed to load.")
Beispiel #5
0
    def setup(self):

        self.object_mask = np.loadtxt("/home/samuroff/mask_template.txt")

        # WCS
        wcs_path = "/share/des/disc2/y1/OPS/coadd/20141118000051_DES0014-4414/coadd/DES0014-4414_r.fits.fz"
        orig_col = 1000
        orig_row = 1000
        image_pos = galsim.PositionD(orig_col, orig_row)
        self.wcs = galsim.FitsWCS(wcs_path)

        # im3shape config
        self.opt = p3s.Options(
            "/home/samuroff/shear_pipeline/end-to-end/end-to-end_code/config_files/im3shape/params_disc.ini"
        )
Beispiel #6
0
    def analyse1(self,
                 central_ellipticity,
                 dneigh=20,
                 central_flux=1912.0,
                 psf_size=3.7,
                 neighbour_flux=1912.0,
                 neighbour_size=3.2):
        # Level 1 - loop over SNR
        #-----------------------------------------------------------------------

        self.m = {}
        self.m[1] = []
        self.m[2] = []
        self.snr = []

        self.dneigh = 20
        self.central_flux = 1912.0
        self.psf_size = 3.7
        self.neighbour_flux = 1912.0
        self.neighbour_size = 3.2

        print "Toy model has a central galaxy with shape ", central_ellipticity
        self.e1 = central_ellipticity[0]
        self.e2 = central_ellipticity[1]

        # Setup a dummy wcs
        # We load it here to avoid too much unncessary io
        # In fact it should provide a skeleton only, since we overwrite the Jacobian with an identity matrix
        wcs_path = "/share/des/disc2/y1/OPS/coadd/20141118000051_DES0014-4414/coadd/DES0014-4414_r.fits.fz"
        orig_col = 1000
        orig_row = 1000
        image_pos = galsim.PositionD(orig_col, orig_row)
        self.wcs = galsim.FitsWCS(wcs_path)
        self.opt = p3s.Options(
            "/home/samuroff/shear_pipeline/end-to-end/end-to-end_code/config_files/im3shape/params_disc.ini"
        )

        self.binning = np.logspace(1, 3.5, 12)

        # Cycle over the central flux, as a proxy for SNR
        for i, proxy in enumerate(self.binning):
            print "Level 1 iteration: %d %f" % (i, proxy)
            self.do_position_loop(proxy)

        print "Done all loops"
Beispiel #7
0
	def get_wcs(self, iobj, iexp):

		wcs_path = self.get_source_path(iobj, iexp)

		wcs_path = check_wcs(wcs_path)

		orig_col = self['orig_col'][iobj][iexp]
		orig_row = self['orig_row'][iobj][iexp]        
		image_pos = galsim.PositionD(orig_col,orig_row)
		wcs = galsim.FitsWCS(wcs_path)

		ix = int(math.floor(image_pos.x ))
		iy = int(math.floor(image_pos.y ))

		# Offset of the galaxy centroid from the stamp centre
		offset = (image_pos - galsim.PositionD(ix,iy))
		offset= galsim.PositionD(offset.x+0.5, offset.y+0.5)

		return wcs.local(image_pos), offset
Beispiel #8
0
    def __init__(self, file_name, image_file_name=None, wcs=None, dir=None):

        if dir:
            if not isinstance(file_name, basestring):
                raise ValueError("Cannot provide dir and an HDU instance")
            import os
            file_name = os.path.join(dir, file_name)
            if image_file_name is not None:
                image_file_name = os.path.join(dir, image_file_name)
        self.file_name = file_name
        if image_file_name:
            if wcs is not None:
                raise AttributeError(
                    "Cannot provide both image_file_name and wcs")
            self.wcs = galsim.FitsWCS(image_file_name)
        elif wcs:
            self.wcs = wcs
        else:
            self.wcs = None
        self.read()
Beispiel #9
0
def get_galsim_wcs(*, image_path, image_ext):
    """Read the WCS solution of an image into a galsim WCS object.

    Parameters
    ----------
    image_path : str
        The path to the image.
    image_ext : int or str
        The extension with the WCS information.

    Returns
    -------
    wcs : galsim WCS
        The WCS object.
    """
    hd = fitsio.read_header(
        image_path, ext=image_ext)
    hd = {k.upper(): hd[k] for k in hd if k is not None}
    wcs = galsim.FitsWCS(header=hd)
    assert not isinstance(wcs, galsim.PixelScale)  # this has been a problem
    return wcs
Beispiel #10
0
def get_fixed_gaussian_psf(options, psf_size, psf_e1, psf_e2, wcs=None):
    "This is slow - for test runs only."
    import galsim
    psf_box = (options.stamp_size + options.padding) * options.upsampling

    #Get the localized WCS information
    if wcs is None:
        wcs_path = "/share/des/disc2/y1/OPS/coadd/20141118000051_DES0014-4414/coadd/DES0014-4414_r.fits.fz"
        wcs = galsim.FitsWCS(wcs_path)

    orig_col = 1000
    orig_row = 1000
    image_pos = galsim.PositionD(orig_col, orig_row)
    local_wcs = wcs.local(image_pos)
    local_wcs._dudx = 1.0 / options.upsampling
    local_wcs._dudy = 0.0 / options.upsampling
    local_wcs._dvdx = 0.0 / options.upsampling
    local_wcs._dvdy = 1.0 / options.upsampling
    A = np.array([[local_wcs._dudx, local_wcs._dudy],
                  [local_wcs._dvdx, local_wcs._dvdy]])
    local_wcs._det = np.linalg.det(A)

    #Generate the PSF in sky coordinates
    pix = wcs.toWorld(galsim.Pixel(0.27), image_pos=image_pos)
    psf_sky = galsim.Convolve([galsim.Gaussian(fwhm=psf_size), pix])
    psf_sky = galsim.Gaussian(fwhm=psf_size)
    pshear = galsim.Shear(g1=psf_e1, g2=psf_e2)
    psf_sky = psf_sky.shear(pshear)

    psf_stamp = psf_sky.drawImage(wcs=local_wcs,
                                  nx=psf_box,
                                  ny=psf_box,
                                  method='no_pixel')
    psf_stamp_array = psf_stamp.array.copy()
    assert psf_stamp_array.shape == (psf_box, psf_box)
    return psf_sky, psf_stamp.array.copy()
Beispiel #11
0
def skip_roman_wcs():
    """Test the Roman WCS routines against ones provided by the Roman project office.
    """
    # This test is out of date and is not run, but since it was a useful test, the code is kept here
    # as a reminder to reinstate it if/when we get an updated version of the WCS software from the
    # Roman project office for cycle 7+.  Everything below this comment is the original code from
    # GalSim v1.4.
    ######################################################################################3
    # The standard against which we will compare is the output of some software provided by Jeff
    # Kruk.  The files used here were generated by Rachel on her Macbook using the script in
    # roman_files/make_standards.sh, and none of the parameters below can be changed without
    # modifying and rerunning that script.  We use 4 sky positions and rotation angles (2 defined
    # using the focal plane array, 2 using the observatory coordinates), and in each case, use a
    # different SCA for our tests.  We will simply read in the stored WCS and generate new ones, and
    # check that they have the right value of SCA center and pixel scale at the center, and that if
    # we offset by 500 pixels in some direction that gives the same sky position in each case.
    ra_test = [127., 307.4, -61.52, 0.0]
    dec_test = [-70., 50., 22.7, 0.0]
    pa_test = [160., 79., 23.4, -3.1]
    sca_test = [2, 13, 7, 18]
    import datetime
    ve = datetime.datetime(2025, 3, 20, 9, 2, 0)
    date_test = [ve, ve, ve, datetime.date(2025, 6, 20)]
    pa_is_fpa_test = [True, False, True, False]

    dist_arcsec = []
    dist_2_arcsec = []
    pix_area_ratio = []
    for i_test in range(len(ra_test)):
        # Make the WCS for this test.
        world_pos = galsim.CelestialCoord(ra_test[i_test] * galsim.degrees,
                                          dec_test[i_test] * galsim.degrees)
        if i_test == 0:
            # Just for this case, we want to get the WCS for all SCAs.  This will enable some
            # additional tests that we don't do for the other test case.
            gs_wcs_dict = galsim.roman.getWCS(PA=pa_test[i_test] *
                                              galsim.degrees,
                                              world_pos=world_pos,
                                              PA_is_FPA=pa_is_fpa_test[i_test],
                                              date=date_test[i_test])
            np.testing.assert_equal(
                len(gs_wcs_dict),
                galsim.roman.n_sca,
                err_msg='WCS dict has wrong length: %d vs. %d' %
                (len(gs_wcs_dict), galsim.roman.n_sca))
        else:
            # Use the SCAs keyword to just get the WCS for the SCA that we want.
            gs_wcs_dict = galsim.roman.getWCS(PA=pa_test[i_test] *
                                              galsim.degrees,
                                              world_pos=world_pos,
                                              PA_is_FPA=pa_is_fpa_test[i_test],
                                              SCAs=sca_test[i_test],
                                              date=date_test[i_test])
            np.testing.assert_equal(
                len(gs_wcs_dict),
                1,
                err_msg='WCS dict has wrong length: %d vs. %d' %
                (len(gs_wcs_dict), 1))

        # Read in reference.
        test_file = 'test%d_sca_%02d.fits' % (i_test + 1, sca_test[i_test])
        ref_wcs = galsim.FitsWCS(os.path.join('roman_files', test_file))

        gs_wcs = gs_wcs_dict[sca_test[i_test]]

        # Check center position:
        im_cent_pos = galsim.PositionD(galsim.roman.n_pix / 2.,
                                       galsim.roman.n_pix / 2)
        ref_cent_pos = ref_wcs.toWorld(im_cent_pos)
        gs_cent_pos = gs_wcs.toWorld(im_cent_pos)
        dist_arcsec.append(
            ref_cent_pos.distanceTo(gs_cent_pos) / galsim.arcsec)

        # Check pixel area
        rat = ref_wcs.pixelArea(image_pos=im_cent_pos) / gs_wcs.pixelArea(
            image_pos=im_cent_pos)
        pix_area_ratio.append(rat - 1.)

        # Check another position, just in case rotations are messed up.
        im_other_pos = galsim.PositionD(im_cent_pos.x + 500.,
                                        im_cent_pos.y - 200.)
        ref_other_pos = ref_wcs.toWorld(im_other_pos)
        gs_other_pos = gs_wcs.toWorld(im_other_pos)
        dist_2_arcsec.append(
            ref_other_pos.distanceTo(gs_other_pos) / galsim.arcsec)

        if i_test == 0:
            # For just one of our tests cases, we'll do some additional tests.  These will target
            # the findSCA() functionality.  First, we'll choose an SCA and check that its center is
            # found to be in that SCA.
            found_sca = galsim.roman.findSCA(gs_wcs_dict, gs_cent_pos)
            np.testing.assert_equal(
                found_sca,
                sca_test[i_test],
                err_msg='Did not find SCA center position to be on that SCA!')

            # Then, we go to a place that should be off the side by a tiny bit, and check that it is
            # NOT on an SCA if we exclude borders, but IS on the SCA if we include borders.
            im_off_edge_pos = galsim.PositionD(-2., galsim.roman.n_pix / 2.)
            world_off_edge_pos = gs_wcs.toWorld(im_off_edge_pos)
            found_sca = galsim.roman.findSCA(gs_wcs_dict, world_off_edge_pos)
            assert found_sca is None
            found_sca = galsim.roman.findSCA(gs_wcs_dict,
                                             world_off_edge_pos,
                                             include_border=True)
            np.testing.assert_equal(
                found_sca,
                sca_test[i_test],
                err_msg='Did not find slightly off-edge position on the SCA'
                ' when including borders!')

    np.testing.assert_array_less(
        np.array(dist_arcsec),
        np.ones(len(ra_test)) * galsim.roman.pixel_scale / 100,
        err_msg=
        'For at least one WCS, center offset from reference was > 0.01(pixel scale).'
    )
    np.testing.assert_array_less(
        np.array(dist_2_arcsec),
        np.ones(len(ra_test)) * galsim.roman.pixel_scale / 100,
        err_msg=
        'For at least one WCS, other offset from reference was > 0.01(pixel scale).'
    )
    np.testing.assert_array_less(
        np.array(pix_area_ratio),
        np.ones(len(ra_test)) * 0.0001,
        err_msg=
        'For at least one WCS, pixel areas differ from reference by >0.01%.')
Beispiel #12
0
def simImage(sourceDir,imFile,catFile,psfFile,outFile):

    """ 

    Create a simulated image using PSFEx modelled PSFs and noise properties of the source image 

    Input: sourceDir: input directory data
           imFile: imput image file name
           catFile: catalogue file (output from SeXtractor)
           psfFile: psf model (output from PSFEx)
           outFile: name of output file for image

    Output: writes to fits file. 

    The catFile must contain the fields X_IMAGE, Y_IMAGE, FLUX_APER (or the code to 
    be changed to equivalent for positions of sources and integrated flux). 

    """
    #load necessary stuff from files.

    #NOte that the MCS image files have two HDUs, one with
    #the WCS information, one with the image information. 
    
    galHdr1 = galsim.FitsHeader(imFile, dir=sourceDir, hdu=0)
    galHdr2 = galsim.FitsHeader(imFile, dir=sourceDir, hdu=1)
    cat = galsim.Catalog(catFile, hdu=2, dir=sourceDir, file_type="FITS")
    psfex=des.DES_PSFEx(psfFile,imFile,dir=sourceDir)
    image=galsim.fits.read(imFile,sourceDir,hdu=1)
    
    #get setup the image. match the (currently trivial) WCS with the image, and
    #create a blank image
    
    wcs = galsim.FitsWCS(header=galHdr1)
    xSize=galHdr2['NAXIS1']
    ySize=galHdr2['NAXIS2']
    simImage = galsim.Image(xSize, ySize, wcs=wcs)

    #some definitions for extracting catalogue columsn
    xCol="X_IMAGE"
    yCol="Y_IMAGE"
    fluxCol="FLUX_APER"

    #get noise statistics. Read in the catalogue positions to estimate the centre
    #of the image in whatever rotation it has. This is so we get the noise statistics
    #from teh mask region, excludin the rest of the image. 
    
    xVals=cat.data[xCol]
    yVals=cat.data[yCol]
    xMean=int(xVals.mean())
    yMean=int(yVals.mean())
    radius=1800

    subIm=image.array[int(xMean-radius):int(xMean+radius),int(yMean-radius):int(yMean+radius)]
    im,a,b=sigmaclip(subIm.ravel(),5,5)

    skyLevel=im.mean()
    skySigma=im.std()
    gain = skyLevel / skySigma**2  #this definition from teh galsim tutorials
    nobj = cat.nobjects

    print('Catalog has ',nobj,' objects. Sky level is ',int(skyLevel),' Sky sigma is ',int(skySigma))

    #now cycle over the catalogue.
    
    for k in range(nobj):

        #get position and flux
        x = cat.getFloat(k,xCol)
        y = cat.getFloat(k,yCol)
        flux = cat.getFloat(k,fluxCol)*5

        #some position calculation for the galsim routines
        # + 0.5 to account for even-size postage stamps
        x=x+0.5
        y=y+0.5
        ix = int(math.floor(x+0.5))
        iy = int(math.floor(y+0.5))
        dx = x-ix
        dy = y-iy

        imagePos = galsim.PositionD(x,y)
        offset = galsim.PositionD(dx,dy)

        #calculate PSF for given position and flux
        psf=psfex.getPSF(imagePos).withFlux(flux)

        #make image
        stamp = psf.drawImage(wcs=wcs.local(imagePos), offset=offset, method='no_pixel')
        stamp.setCenter(ix,iy)

        #and place on image, taking into consideration edges
        bounds = stamp.bounds & simImage.bounds
        simImage[bounds] += stamp[bounds]

    #now that we've done all the spots, add noise

    #background sky level
    simImage += skyLevel

    #CCD noise
    random_seed = 1339201
    rng=galsim.BaseDeviate(random_seed)
    noise = galsim.CCDNoise(rng, gain=gain)

    #poisonnian noise
    simImage.addNoise(noise)
    noise = galsim.PoissonNoise(rng, sky_level=skyLevel)
    simImage.addNoise(noise)

    #and dump to a file. Will overwrite existing file.
    simImage.write(outFile,clobber=True)
Beispiel #13
0
def test_flat():
    """Test building a flat field image using the Silicon class.
    """
    # Note: This test is based on a script devel/lsst/treering_flat.py

    if __name__ == '__main__':
        nx = 200
        ny = 200
        nflats = 20
        niter = 50
        toler = 0.01
    else:
        nx = 50
        ny = 50
        nflats = 3
        niter = 20  # Seem to really need 20 or more iterations to get covariances close.
        toler = 0.05

    counts_total = 80.e3
    counts_per_iter = counts_total / niter

    # Silicon sensor with tree rings
    seed = 31415
    rng = galsim.UniformDeviate(seed)
    treering_func = galsim.SiliconSensor.simple_treerings(0.26, 47)
    treering_center = galsim.PositionD(0,0)
    sensor = galsim.SiliconSensor(rng=rng,
                                   treering_func=treering_func, treering_center=treering_center)

    # Use a non-trivial WCS to make sure that works properly.
    wcs = galsim.FitsWCS('fits_files/tnx.fits')
    # We add on a border of 2 pixels, since the outer row/col get a little messed up by photons
    # falling off the edge, but not coming on from the other direction.
    # We do 2 rows/cols rather than just 1 to be safe, since I think diffusion can probably go
    # 2 pixels, even though the deficit is only really evident on the outer pixel.
    nborder = 2
    base_image = galsim.ImageF(nx+2*nborder, ny+2*nborder, wcs=wcs)
    base_image.wcs.makeSkyImage(base_image, sky_level=1.)

    # Rescale so that the mean sky level per pixel is skyCounts
    mean_pixel_area = base_image.array.mean()
    sky_level_per_iter = counts_per_iter / mean_pixel_area  # in ADU/arcsec^2 now.
    base_image *= sky_level_per_iter

    # The base_image now has the right level to account for the WCS distortion, but not any sensor
    # effects.
    # This is the noise-free level that we want to add each iteration modulated by the sensor.

    noise = galsim.PoissonNoise(rng)
    flats = []

    for n in range(nflats):
        print('n = ',n)
        # image is the image that we will build up in steps.
        image = galsim.ImageF(nx+2*nborder, ny+2*nborder, wcs=wcs)

        for i in range(niter):
            # temp is the additional flux we will add to the image in this iteration.
            # Start with the right area due to the sensor effects.
            temp = sensor.calculate_pixel_areas(image)
            temp /= temp.array.mean()

            # Multiply by the base image to get the right mean level and wcs effects
            temp *= base_image

            # Finally, add noise.  What we have here so far is the expectation value in each pixel.
            # We need to realize this according to Poisson statistics with these means.
            temp.addNoise(noise)

            # Add this to the image we are building up.
            image += temp

        # Cut off the outer border where things don't work quite right.
        image = image.subImage(galsim.BoundsI(1+nborder,nx+nborder,1+nborder,ny+nborder))
        flats.append(image.array)

    # These are somewhat noisy, so compute for all pairs and average them.
    mean = var = cov01 = cov10 = cov11a = cov11b = cov02 = cov20 = 0
    n = len(flats)
    npairs = 0

    for i in range(n):
        flati = flats[i]
        print('mean ',i,' = ',flati.mean())
        mean += flati.mean()
        for j in range(i+1,n):
            flatj = flats[j]
            diff = flati - flatj
            var += diff.var()/2
            cov01 += np.mean(diff[1:,:] * diff[:-1,:])
            cov10 += np.mean(diff[:,1:] * diff[:,:-1])
            cov11a += np.mean(diff[1:,1:] * diff[:-1,:-1])
            cov11b += np.mean(diff[1:,:-1] * diff[:-1,1:])
            cov02 += np.mean(diff[2:,:] * diff[:-2,:])
            cov20 += np.mean(diff[:,2:] * diff[:,:-2])
            npairs += 1
    mean /= n
    var /= npairs
    cov01 /= npairs
    cov10 /= npairs
    cov11a /= npairs
    cov11b /= npairs
    cov02 /= npairs
    cov20 /= npairs

    print('var(diff)/2 = ',var, 0.93*counts_total)
    print('cov01 = ',cov01, 0.03*counts_total)   # Note: I don't actually know if these are
    print('cov10 = ',cov10, 0.015*counts_total)  # the right covariances...
    print('cov11a = ',cov11a, cov11a/counts_total)
    print('cov11b = ',cov11b, cov11b/counts_total)
    print('cov02 = ',cov02, cov02/counts_total)
    print('cov20 = ',cov20, cov20/counts_total)

    # Mean should be close to target counts
    np.testing.assert_allclose(mean, counts_total, rtol=toler)
    # Variance is a bit less than the mean due to B/F.
    np.testing.assert_allclose(var, 0.93 * counts_total, rtol=toler)
    # 01 and 10 covariances are significant.
    np.testing.assert_allclose(cov01, 0.03 * counts_total, rtol=30*toler)
    np.testing.assert_allclose(cov10, 0.015 * counts_total, rtol=60*toler)
    # The rest are small
    np.testing.assert_allclose(cov11a / counts_total, 0., atol=2*toler)
    np.testing.assert_allclose(cov11b / counts_total, 0., atol=2*toler)
    np.testing.assert_allclose(cov20 / counts_total, 0., atol=2*toler)
    np.testing.assert_allclose(cov02 / counts_total, 0., atol=2*toler)
Beispiel #14
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)
Beispiel #15
0
def test_meds():
    """
    Create two objects, each with three exposures. Save them to a MEDS file.
    Load the MEDS file. Compare the created objects with the one read by MEDS.
    """
    # initialise empty MultiExposureObject list
    objlist = []

    # we will be using 2 objects for testing, each with 3 cutouts
    n_obj_test = 2
    n_cut_test = 3

    # set the image size
    box_size = 32

    # first obj
    img11 = galsim.Image(box_size, box_size, init_value=111)
    img12 = galsim.Image(box_size, box_size, init_value=112)
    img13 = galsim.Image(box_size, box_size, init_value=113)
    seg11 = galsim.Image(box_size, box_size, init_value=121)
    seg12 = galsim.Image(box_size, box_size, init_value=122)
    seg13 = galsim.Image(box_size, box_size, init_value=123)
    wth11 = galsim.Image(box_size, box_size, init_value=131)
    wth12 = galsim.Image(box_size, box_size, init_value=132)
    wth13 = galsim.Image(box_size, box_size, init_value=133)
    psf11 = galsim.Image(box_size, box_size, init_value=141)
    psf12 = galsim.Image(box_size, box_size, init_value=142)
    psf13 = galsim.Image(box_size, box_size, init_value=143)
    dudx = 11.1
    dudy = 11.2
    dvdx = 11.3
    dvdy = 11.4
    x0 = 11.5
    y0 = 11.6
    wcs11 = galsim.AffineTransform(dudx, dudy, dvdx, dvdy,
                                   galsim.PositionD(x0, y0))
    dudx = 12.1
    dudy = 12.2
    dvdx = 12.3
    dvdy = 12.4
    wcs12 = galsim.JacobianWCS(dudx, dudy, dvdx, dvdy)
    wcs13 = galsim.PixelScale(13)

    # create lists
    images = [img11, img12, img13]
    weight = [wth11, wth12, wth13]
    seg = [seg11, seg12, seg13]
    psf = [psf11, psf12, psf13]
    wcs = [wcs11, wcs12, wcs13]

    # create object
    obj1 = galsim.des.MultiExposureObject(images=images,
                                          weight=weight,
                                          seg=seg,
                                          psf=psf,
                                          wcs=wcs,
                                          id=1)

    # second obj
    img21 = galsim.Image(box_size, box_size, init_value=211)
    img22 = galsim.Image(box_size, box_size, init_value=212)
    img23 = galsim.Image(box_size, box_size, init_value=213)
    seg21 = galsim.Image(box_size, box_size, init_value=221)
    seg22 = galsim.Image(box_size, box_size, init_value=222)
    seg23 = galsim.Image(box_size, box_size, init_value=223)
    wth21 = galsim.Image(box_size, box_size, init_value=231)
    wth22 = galsim.Image(box_size, box_size, init_value=332)
    wth23 = galsim.Image(box_size, box_size, init_value=333)
    psf21 = galsim.Image(box_size, box_size, init_value=241)
    psf22 = galsim.Image(box_size, box_size, init_value=342)
    psf23 = galsim.Image(box_size, box_size, init_value=343)

    dudx = 21.1
    dudy = 21.2
    dvdx = 21.3
    dvdy = 21.4
    x0 = 21.5
    y0 = 21.6
    wcs21 = galsim.AffineTransform(dudx, dudy, dvdx, dvdy,
                                   galsim.PositionD(x0, y0))
    dudx = 22.1
    dudy = 22.2
    dvdx = 22.3
    dvdy = 22.4
    wcs22 = galsim.JacobianWCS(dudx, dudy, dvdx, dvdy)
    wcs23 = galsim.PixelScale(23)

    # create lists
    images = [img21, img22, img23]
    weight = [wth21, wth22, wth23]
    seg = [seg21, seg22, seg23]
    psf = [psf21, psf22, psf23]
    wcs = [wcs21, wcs22, wcs23]

    # create object
    # This time put the wcs in the image and get it there.
    img21.wcs = wcs21
    img22.wcs = wcs22
    img23.wcs = wcs23
    obj2 = galsim.des.MultiExposureObject(images=images,
                                          weight=weight,
                                          seg=seg,
                                          psf=psf,
                                          id=2)

    obj3 = galsim.des.MultiExposureObject(images=images, id=3)

    # create an object list
    objlist = [obj1, obj2]

    # save objects to MEDS file
    filename_meds = 'output/test_meds.fits'
    galsim.des.WriteMEDS(objlist, filename_meds, clobber=True)

    bad1 = galsim.Image(32, 48, init_value=0)
    bad2 = galsim.Image(35, 35, init_value=0)
    bad3 = galsim.Image(48, 48, init_value=0)

    with assert_raises(TypeError):
        galsim.des.MultiExposureObject(images=img11)
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[bad1])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[bad2])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[img11, bad3])
    with assert_raises(TypeError):
        galsim.des.MultiExposureObject(images=images, weight=wth11)
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=images, weight=[])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[img11], weight=[bad3])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[img11], psf=[bad1])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[img11], psf=[bad2])
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[img11, img12],
                                       psf=[bad2, psf12])
    with assert_raises(TypeError):
        galsim.des.MultiExposureObject(images=images, wcs=wcs11)
    celestial_wcs = galsim.FitsWCS("DECam_00154912_12_header.fits",
                                   dir='des_data')
    with assert_raises(galsim.GalSimValueError):
        galsim.des.MultiExposureObject(images=[img11], wcs=[celestial_wcs])

    # Check the one with no psf, weight, etc.
    filename_meds2 = 'output/test_meds_image_only.fits'
    galsim.des.WriteMEDS([obj3], filename_meds2, clobber=True)

    # Note that while there are no tests prior to this, the above still checks for
    # syntax errors in the meds creation software, so it's still worth running as part
    # of the normal unit tests.
    # But for the rest of the tests, we'll use the meds module to make sure our code
    # stays in sync with any changes there.
    try:
        import meds
        # Meds will import this, so check for this too.
        import fitsio
    except ImportError:
        print(
            'Failed to import either meds or fitsio.  Unable to do tests of meds file.'
        )
        return

    # Run meds module's validate function
    try:
        meds.util.validate_meds(filename_meds)
        meds.util.validate_meds(filename_meds2)
    except AttributeError:
        print(
            'Seems to be the wrong meds package.  Unable to do tests of meds file.'
        )
        return

    m = meds.MEDS(filename_meds)

    # Check the image_info extension:
    ref_info = meds.util.get_image_info_dtype(1)
    info = m.get_image_info()
    print('info = ', info)
    for name, dt in ref_info:
        dt = numpy.dtype(dt)
        print(name, dt, info.dtype[name], dt.char, info.dtype[name].char)
        assert name in info.dtype.names, "column %s not present in image_info extension" % name
        # I think S and U for this purpose are equivalent.
        # But I'm finding S in the reference, and U in info.
        c = info.dtype[name].char
        c = 'S' if c == 'U' else c
        assert dt.char == c, "column %s is the wrong type" % name

    # Check the basic structure of the object_data extension
    cat = m.get_cat()
    ref_data = meds.util.get_meds_output_dtype(1)
    for tup in ref_data:
        # Some of these tuples have 3 items, not 2.  The last two are the full dtype tuple.
        name = tup[0]
        if len(tup) == 2:
            dt = tup[1]
        else:
            dt = tup[1:]
        dt = numpy.dtype(dt)
        print(name, dt, cat.dtype[name], dt.char, cat.dtype[name].char)
        assert name in cat.dtype.names, "column %s not present in object_data extension" % name
        assert dt.char == cat.dtype[
            name].char, "column %s is the wrong type" % name

    # Check that we have the right number of objects.
    n_obj = len(cat)
    print('number of objects is %d' % n_obj)
    numpy.testing.assert_equal(n_obj,
                               n_obj_test,
                               err_msg="MEDS file has wrong number of objects")

    # loop over objects and exposures - test get_cutout
    for iobj in range(n_obj):

        # check ID is correct
        numpy.testing.assert_equal(
            cat['id'][iobj],
            iobj + 1,
            err_msg="MEDS file has wrong id for object %d" % iobj)

        # get number of cutouts and check if it's right
        n_cut = cat['ncutout'][iobj]
        numpy.testing.assert_equal(
            n_cut,
            n_cut_test,
            err_msg="MEDS file has wrong ncutout for object %d" % iobj)

        # loop over cutouts
        for icut in range(n_cut):

            # get the images etc to compare with originals
            img = m.get_cutout(iobj, icut, type='image')
            wth = m.get_cutout(iobj, icut, type='weight')
            seg = m.get_cutout(iobj, icut, type='seg')
            psf = m.get_psf(iobj, icut)
            wcs_meds = m.get_jacobian(iobj, icut)
            # Note: col == x, row == y.
            wcs_array_meds = numpy.array([
                wcs_meds['dudcol'], wcs_meds['dudrow'], wcs_meds['dvdcol'],
                wcs_meds['dvdrow'], wcs_meds['col0'], wcs_meds['row0']
            ])

            # compare
            numpy.testing.assert_array_equal(
                img,
                objlist[iobj].images[icut].array,
                err_msg="MEDS cutout has wrong img for object %d" % iobj)
            numpy.testing.assert_array_equal(
                wth,
                objlist[iobj].weight[icut].array,
                err_msg="MEDS cutout has wrong wth for object %d" % iobj)
            numpy.testing.assert_array_equal(
                seg,
                objlist[iobj].seg[icut].array,
                err_msg="MEDS cutout has wrong seg for object %d" % iobj)
            numpy.testing.assert_array_equal(
                psf,
                objlist[iobj].psf[icut].array,
                err_msg="MEDS cutout has wrong psf for object %d" % iobj)
            wcs_orig = objlist[iobj].wcs[icut]
            wcs_array_orig = numpy.array([
                wcs_orig.dudx, wcs_orig.dudy, wcs_orig.dvdx, wcs_orig.dvdy,
                wcs_orig.origin.x, wcs_orig.origin.y
            ])
            numpy.testing.assert_array_equal(
                wcs_array_meds,
                wcs_array_orig,
                err_msg="MEDS cutout has wrong wcs for object %d" % iobj)

        # get the mosaic to compare with originals
        img = m.get_mosaic(iobj, type='image')
        wth = m.get_mosaic(iobj, type='weight')
        seg = m.get_mosaic(iobj, type='seg')
        # There is currently no get_mosaic option for the psfs.
        #psf = m.get_mosaic( iobj, type='psf')
        psf = numpy.concatenate(
            [m.get_psf(iobj, icut) for icut in range(n_cut)], axis=0)

        # get the concatenated images - create the true mosaic
        true_mosaic_img = numpy.concatenate(
            [x.array for x in objlist[iobj].images], axis=0)
        true_mosaic_wth = numpy.concatenate(
            [x.array for x in objlist[iobj].weight], axis=0)
        true_mosaic_seg = numpy.concatenate(
            [x.array for x in objlist[iobj].seg], axis=0)
        true_mosaic_psf = numpy.concatenate(
            [x.array for x in objlist[iobj].psf], axis=0)

        # compare
        numpy.testing.assert_array_equal(
            true_mosaic_img,
            img,
            err_msg="MEDS mosaic has wrong img for object %d" % iobj)
        numpy.testing.assert_array_equal(
            true_mosaic_wth,
            wth,
            err_msg="MEDS mosaic has wrong wth for object %d" % iobj)
        numpy.testing.assert_array_equal(
            true_mosaic_seg,
            seg,
            err_msg="MEDS mosaic has wrong seg for object %d" % iobj)
        numpy.testing.assert_array_equal(
            true_mosaic_psf,
            psf,
            err_msg="MEDS mosaic has wrong psf for object %d" % iobj)
    # But here we build up to a much higher flux level where B/F is important.

    t0 = time.time()

    rng = galsim.UniformDeviate(seed)

    treering_func = galsim.SiliconSensor.simple_treerings(
        treering_amplitude, treering_period)

    niter = int(counts_total / counts_per_iter + 0.5)
    counts_per_iter = counts_total / niter  # Recalculate in case not even multiple.
    print('Total counts = {} = {} * {}'.format(counts_total, niter,
                                               counts_per_iter))

    # Not an LSST wcs, but just make sure this works properly with a non-trivial wcs.
    wcs = galsim.FitsWCS('../../tests/fits_files/tnx.fits')

    base_image = galsim.ImageF(nx + 2 * nborder, ny + 2 * nborder, wcs=wcs)
    print('image bounds = ', base_image.bounds)

    # nrecalc is actually irrelevant here, since a recalculation will be forced on each iteration.
    # Which is really the point.  We need to set coundsPerIter appropriately so that the B/F effect
    # doesn't change *too* much between iterations.
    sensor = galsim.SiliconSensor(rng=rng,
                                  treering_func=treering_func,
                                  treering_center=treering_center)

    # We also need to account for the distortion of the wcs across the image.
    # This expects sky_level in ADU/arcsec^2, not ADU/pixel.
    base_image.wcs.makeSkyImage(base_image, sky_level=1.)
    base_image.write('wcs_area.fits')
Beispiel #17
0
    def generate(self,
                 dneigh=20,
                 central_flux=1912.0,
                 psf_size=3.7,
                 neighbour_flux=1912.0,
                 neighbour_size=3.2,
                 vary="psf_e"):
        # PSF leakage toy model
        #-----------------------------------------------------------------------
        g_theta = {}
        theta = np.linspace(0, 2, 50) * np.pi
        self.g = {}
        self.g["e1"] = []
        self.g["e2"] = []
        ang = []

        # Setup a dummy wcs
        # We load it here to avoid too much unncessary io
        # In fact it should provide a skeleton only, since we overwrite the Jacobian with an identity matrix
        wcs_path = "/share/des/disc2/y1/OPS/coadd/20141118000051_DES0014-4414/coadd/DES0014-4414_r.fits.fz"
        orig_col = 1000
        orig_row = 1000
        image_pos = galsim.PositionD(orig_col, orig_row)
        wcs = galsim.FitsWCS(wcs_path)
        opt = p3s.Options(
            "/home/samuroff/shear_pipeline/end-to-end/end-to-end_code/config_files/im3shape/params_disc.ini"
        )

        binning = {
            "psf_e1": np.linspace(-0.2, 0.2, 12),
            "cent_e1": [-0.65, 0.65]
        }
        self.binning = binning[vary]

        # Cycle over psf ellipticities
        for e in self.binning:
            if vary == "psf_e1":
                pe = e
                ce = 0
            elif vary == "cent_e1":
                pe = 0
                ce = e
            g_theta["e1"] = []
            g_theta["e2"] = []
            ang = []
            # For each psf ellipticity average over a ring of neighbour positions
            # For the moment we hardcode the other relevant parameters to their mean values from the simulation
            for i, t in enumerate(theta):
                x = dneigh * np.cos(t)
                y = dneigh * np.sin(t)
                gal, psf = setup_simple(boxsize=48,
                                        shear=(ce, 0.0),
                                        flux=central_flux,
                                        psf_ellipticity=(pe, 0.0),
                                        psf_size=psf_size,
                                        neighbour_ellipticity=(0.0, 0.0),
                                        neighbour=[x, y],
                                        neighbour_flux=neighbour_flux,
                                        neighbour_size=neighbour_size,
                                        wcs=wcs,
                                        opt=opt)
                res = run(gal, psf, opt=opt)
                g_theta["e1"].append(res.e1)
                gal, psf = setup_simple(boxsize=48,
                                        shear=(ce, 0.0),
                                        flux=central_flux,
                                        psf_ellipticity=(pe, 0.0),
                                        psf_size=psf_size,
                                        neighbour_ellipticity=(0.0, 0.0),
                                        neighbour=[np.inf, np.inf],
                                        neighbour_flux=neighbour_flux,
                                        neighbour_size=neighbour_size,
                                        wcs=wcs,
                                        opt=opt)
                res = run(gal, psf, opt=opt)
                g_theta["e2"].append(res.e1)
                ang.append(t)
            self.g["e1"].append(np.mean(g_theta["e1"]))
            self.g["e2"].append(np.mean(g_theta["e2"]))

        for k in self.g.keys():
            self.g[k] = np.array(self.g[k])
Beispiel #18
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])
Beispiel #19
0
config = desc.imsim.read_config()

obs_md, phot_params, _ = desc.imsim.parsePhoSimInstanceFile(args.instcat,
                                                            numRows=30)
sensor_list = args.sensors.split('^') if args.sensors is not None \
    else args.sensors
rng = galsim.UniformDeviate(args.seed)
niter = int(args.counts_total / args.counts_per_iter + 0.5)
counts_per_iter = args.counts_total / niter
logger = desc.imsim.get_logger(args.log_level, name='make_flats')

visit = obs_md.OpsimMetaData['obshistID']

camera_wrapper = LSSTCameraWrapper()

wcs = galsim.FitsWCS(args.wcs_file) if args.wcs_file is not None else None

for det in camera_wrapper.camera:
    det_name = det.getName()
    if (det.getType() != cameraGeom.SCIENCE
            or (args.sensors is not None and det_name not in sensor_list)):
        continue
    logger.info("processing %s", det_name)
    gs_det = make_galsim_detector(camera_wrapper, det_name, phot_params,
                                  obs_md)
    desc.imsim.add_treering_info([gs_det])
    my_flat = desc.imsim.make_flat(gs_det,
                                   counts_per_iter,
                                   niter,
                                   rng,
                                   logger=logger,
Beispiel #20
0
def test_withOrigin():
    from test_wcs import Cubic

    # First EuclideantWCS types:

    wcs_list = [
        galsim.OffsetWCS(0.3, galsim.PositionD(1, 1), galsim.PositionD(10,
                                                                       23)),
        galsim.OffsetShearWCS(0.23, galsim.Shear(g1=0.1, g2=0.3),
                              galsim.PositionD(12, 43)),
        galsim.AffineTransform(0.01, 0.26, -0.26, 0.02,
                               galsim.PositionD(12, 43)),
        galsim.UVFunction(ufunc=lambda x, y: 0.2 * x,
                          vfunc=lambda x, y: 0.2 * y),
        galsim.UVFunction(ufunc=lambda x, y: 0.2 * x,
                          vfunc=lambda x, y: 0.2 * y,
                          xfunc=lambda u, v: u / scale,
                          yfunc=lambda u, v: v / scale),
        galsim.UVFunction(ufunc='0.2*x + 0.03*y', vfunc='0.01*x + 0.2*y'),
    ]

    color = 0.3
    for wcs in wcs_list:
        # Original version of the shiftOrigin tests in do_nonlocal_wcs using deprecated name.
        new_origin = galsim.PositionI(123, 321)
        wcs3 = check_dep(wcs.withOrigin, new_origin)
        assert wcs != wcs3, name + ' is not != wcs.withOrigin(pos)'
        wcs4 = wcs.local(wcs.origin, color=color)
        assert wcs != wcs4, name + ' is not != wcs.local()'
        assert wcs4 != wcs, name + ' is not != wcs.local() (reverse)'
        world_origin = wcs.toWorld(wcs.origin, color=color)
        if wcs.isUniform():
            if wcs.world_origin == galsim.PositionD(0, 0):
                wcs2 = wcs.local(wcs.origin,
                                 color=color).withOrigin(wcs.origin)
                assert wcs == wcs2, name + ' is not equal after wcs.local().withOrigin(origin)'
            wcs2 = wcs.local(wcs.origin,
                             color=color).withOrigin(wcs.origin,
                                                     wcs.world_origin)
            assert wcs == wcs2, name + ' not equal after wcs.local().withOrigin(origin,world_origin)'
        world_pos1 = wcs.toWorld(galsim.PositionD(0, 0), color=color)
        wcs3 = check_dep(wcs.withOrigin, new_origin)
        world_pos2 = wcs3.toWorld(new_origin, color=color)
        np.testing.assert_almost_equal(
            world_pos2.x, world_pos1.x, 7,
            'withOrigin(new_origin) returned wrong world position')
        np.testing.assert_almost_equal(
            world_pos2.y, world_pos1.y, 7,
            'withOrigin(new_origin) returned wrong world position')
        new_world_origin = galsim.PositionD(5352.7, 9234.3)
        wcs5 = check_dep(wcs.withOrigin,
                         new_origin,
                         new_world_origin,
                         color=color)
        world_pos3 = wcs5.toWorld(new_origin, color=color)
        np.testing.assert_almost_equal(
            world_pos3.x, new_world_origin.x, 7,
            'withOrigin(new_origin, new_world_origin) returned wrong position')
        np.testing.assert_almost_equal(
            world_pos3.y, new_world_origin.y, 7,
            'withOrigin(new_origin, new_world_origin) returned wrong position')

    # Now some CelestialWCS types
    cubic_u = Cubic(2.9e-5, 2000., 'u')
    cubic_v = Cubic(-3.7e-5, 2000., 'v')
    center = galsim.CelestialCoord(23 * galsim.degrees, -13 * galsim.degrees)
    radec = lambda x, y: center.deproject_rad(
        cubic_u(x, y) * 0.2, cubic_v(x, y) * 0.2, projection='lambert')
    wcs_list = [
        galsim.RaDecFunction(radec),
        galsim.AstropyWCS('1904-66_TAN.fits', dir='fits_files'),
        galsim.GSFitsWCS('tpv.fits', dir='fits_files'),
        galsim.FitsWCS('sipsample.fits', dir='fits_files'),
    ]

    for wcs in wcs_list:
        # Original version of the shiftOrigin tests in do_celestial_wcs using deprecated name.
        new_origin = galsim.PositionI(123, 321)
        wcs3 = wcs.shiftOrigin(new_origin)
        assert wcs != wcs3, name + ' is not != wcs.shiftOrigin(pos)'
        wcs4 = wcs.local(wcs.origin)
        assert wcs != wcs4, name + ' is not != wcs.local()'
        assert wcs4 != wcs, name + ' is not != wcs.local() (reverse)'
        world_pos1 = wcs.toWorld(galsim.PositionD(0, 0))
        wcs3 = wcs.shiftOrigin(new_origin)
        world_pos2 = wcs3.toWorld(new_origin)
        np.testing.assert_almost_equal(
            world_pos2.distanceTo(world_pos1) / galsim.arcsec, 0, 7,
            'shiftOrigin(new_origin) returned wrong world position')
Beispiel #21
0
def test_wfirst_wcs():
    """Test the WFIRST WCS routines against those from software provided by WFIRST project office.
    """
    # The standard against which we will compare is the output of some software provided by Jeff
    # Kruk.  The files used here were generated by Rachel on her Macbook using the script in
    # wfirst_files/make_standards.sh, and none of the parameters below can be changed without
    # modifying and rerunning that script.  We use 4 sky positions and rotation angles (2 defined
    # using the focal plane array, 2 using the observatory coordinates), and in each case, use a
    # different SCA for our tests.  We will simply read in the stored WCS and generate new ones, and
    # check that they have the right value of SCA center and pixel scale at the center, and that if
    # we offset by 500 pixels in some direction that gives the same sky position in each case.
    ra_test = [127., 307.4, -61.52, 0.0]
    dec_test = [-70., 50., 22.7, 0.0]
    pa_test = [160., 79., 23.4, -3.1]
    sca_test = [2, 13, 7, 18]
    import datetime
    ve = datetime.datetime(2025, 3, 20, 9, 2, 0)
    date_test = [ve, ve, ve, datetime.date(2025, 6, 20)]
    pa_is_fpa_test = [True, False, True, False]

    dist_arcsec = []
    dist_2_arcsec = []
    pix_area_ratio = []
    for i_test in range(len(ra_test)):
        # Make the WCS for this test.
        world_pos = galsim.CelestialCoord(ra_test[i_test] * galsim.degrees,
                                          dec_test[i_test] * galsim.degrees)
        if i_test == 0:
            # Just for this case, we want to get the WCS for all SCAs.  This will enable some
            # additional tests that we don't do for the other test case.
            gs_wcs_dict = galsim.wfirst.getWCS(
                PA=pa_test[i_test] * galsim.degrees,
                world_pos=world_pos,
                PA_is_FPA=pa_is_fpa_test[i_test],
                date=date_test[i_test])
            np.testing.assert_equal(
                len(gs_wcs_dict),
                galsim.wfirst.n_sca,
                err_msg='WCS dict has wrong length: %d vs. %d' %
                (len(gs_wcs_dict), galsim.wfirst.n_sca))
        else:
            # Use the SCAs keyword to just get the WCS for the SCA that we want.
            gs_wcs_dict = galsim.wfirst.getWCS(
                PA=pa_test[i_test] * galsim.degrees,
                world_pos=world_pos,
                PA_is_FPA=pa_is_fpa_test[i_test],
                SCAs=sca_test[i_test],
                date=date_test[i_test])
            np.testing.assert_equal(
                len(gs_wcs_dict),
                1,
                err_msg='WCS dict has wrong length: %d vs. %d' %
                (len(gs_wcs_dict), 1))

        # Read in reference.
        test_file = 'test%d_sca_%02d.fits' % (i_test + 1, sca_test[i_test])
        ref_wcs = galsim.FitsWCS(os.path.join('wfirst_files', test_file))

        gs_wcs = gs_wcs_dict[sca_test[i_test]]

        # Check center position:
        im_cent_pos = galsim.PositionD(galsim.wfirst.n_pix / 2.,
                                       galsim.wfirst.n_pix / 2)
        ref_cent_pos = ref_wcs.toWorld(im_cent_pos)
        gs_cent_pos = gs_wcs.toWorld(im_cent_pos)
        dist_arcsec.append(
            ref_cent_pos.distanceTo(gs_cent_pos) / galsim.arcsec)

        # Check pixel area
        rat = ref_wcs.pixelArea(image_pos=im_cent_pos) / gs_wcs.pixelArea(
            image_pos=im_cent_pos)
        pix_area_ratio.append(rat - 1.)

        # Check another position, just in case rotations are messed up.
        im_other_pos = galsim.PositionD(im_cent_pos.x + 500.,
                                        im_cent_pos.y - 200.)
        ref_other_pos = ref_wcs.toWorld(im_other_pos)
        gs_other_pos = gs_wcs.toWorld(im_other_pos)
        dist_2_arcsec.append(
            ref_other_pos.distanceTo(gs_other_pos) / galsim.arcsec)

        if i_test == 0:
            # For just one of our tests cases, we'll do some additional tests.  These will target
            # the findSCA() functionality.  First, we'll choose an SCA and check that its center is
            # found to be in that SCA.
            found_sca = galsim.wfirst.findSCA(gs_wcs_dict, gs_cent_pos)
            np.testing.assert_equal(
                found_sca,
                sca_test[i_test],
                err_msg='Did not find SCA center position to be on that SCA!')

            # Then, we go to a place that should be off the side by a tiny bit, and check that it is
            # NOT on an SCA if we exclude borders, but IS on the SCA if we include borders.
            im_off_edge_pos = galsim.PositionD(-2., galsim.wfirst.n_pix / 2.)
            world_off_edge_pos = gs_wcs.toWorld(im_off_edge_pos)
            found_sca = galsim.wfirst.findSCA(gs_wcs_dict, world_off_edge_pos)
            assert found_sca is None
            found_sca = galsim.wfirst.findSCA(gs_wcs_dict,
                                              world_off_edge_pos,
                                              include_border=True)
            np.testing.assert_equal(
                found_sca,
                sca_test[i_test],
                err_msg='Did not find slightly off-edge position on the SCA'
                ' when including borders!')

    np.testing.assert_array_less(
        np.array(dist_arcsec),
        np.ones(len(ra_test)) * galsim.wfirst.pixel_scale / 100,
        err_msg=
        'For at least one WCS, center offset from reference was > 0.01(pixel scale).'
    )
    np.testing.assert_array_less(
        np.array(dist_2_arcsec),
        np.ones(len(ra_test)) * galsim.wfirst.pixel_scale / 100,
        err_msg=
        'For at least one WCS, other offset from reference was > 0.01(pixel scale).'
    )
    np.testing.assert_array_less(
        np.array(pix_area_ratio),
        np.ones(len(ra_test)) * 0.0001,
        err_msg=
        'For at least one WCS, pixel areas differ from reference by >0.01%.')

    # Check whether we're allowed to look at certain positions on certain dates.
    # Let's choose RA=90 degrees, dec=10 degrees.
    # We know that it's best to look about 90 degrees from the Sun.  So on the vernal and autumnal
    # equinox, this should be a great place to look, but not midway in between.  We'll use
    # approximate dates for these.
    pos = galsim.CelestialCoord(90. * galsim.degrees, 10. * galsim.degrees)
    import datetime
    assert galsim.wfirst.allowedPos(pos, datetime.date(2025, 3, 20))
    assert galsim.wfirst.allowedPos(pos, datetime.date(2025, 9, 20))
    assert not galsim.wfirst.allowedPos(pos, datetime.date(2025, 6, 20))

    # Finally make sure it does something reasonable for the observatory position angle.
    # When the sun is at (0,0), and we look at (90,0), then +Z points towards the Sun and +Y points
    # North, giving a PA of 0 degrees.
    pos = galsim.CelestialCoord(90. * galsim.degrees, 0. * galsim.degrees)
    test_date = datetime.datetime(2025, 3, 20, 9, 2)
    pa = galsim.wfirst.bestPA(pos, test_date)
    np.testing.assert_almost_equal(pa.rad(), 0., decimal=3)
    # Now make it look at the same RA as the sun but quite different declination.  It wants +Z
    # pointing North toward Sun, so we'll get a -90 degree angle for the PA.
    pos = galsim.CelestialCoord(0. * galsim.degrees, -70. * galsim.degrees)
    pa = galsim.wfirst.bestPA(pos, test_date)
    np.testing.assert_almost_equal(pa.rad(), -np.pi / 2, decimal=3)
Beispiel #22
0
def test_psf():
    """Test the two kinds of PSF files we have in DES.
    """
    data_dir = 'des_data'
    psfex_file = "DECam_00154912_12_psfcat.psf"
    fitpsf_file = "DECam_00154912_12_fitpsf.fits"
    wcs_file = "DECam_00154912_12_header.fits"

    wcs = galsim.FitsWCS(wcs_file, dir=data_dir)

    # We don't require that the files in example_data_dir have been downloaded.  If they
    # haven't, then we just directly set the comparison values that we want here.
    example_data_dir = '../examples/des/des_data'
    cat_file = "DECam_00154912_12_cat.fits"
    image_file = "DECam_00154912_12.fits.fz"

    try:
        cat = galsim.Catalog(cat_file, hdu=2, dir=example_data_dir)
        size = numpy.array(
            [cat.getFloat(i, 'FLUX_RADIUS') for i in range(cat.nobjects)])
        mag = numpy.array(
            [cat.getFloat(i, 'MAG_AUTO') for i in range(cat.nobjects)])
        flags = numpy.array(
            [cat.getInt(i, 'FLAGS') for i in range(cat.nobjects)])
        index = numpy.array(range(cat.nobjects))
        xvals = numpy.array(
            [cat.getFloat(i, 'X_IMAGE') for i in range(cat.nobjects)])
        yvals = numpy.array(
            [cat.getFloat(i, 'Y_IMAGE') for i in range(cat.nobjects)])

        # Pick bright small objects as probable stars
        mask = (flags
                == 0) & (mag < 14) & (mag > 13) & (size > 2) & (size < 2.5)
        idx = numpy.argsort(size[mask])

        # This choice of a star is fairly isolated from neighbors, isn't too near an edge or a tape
        # bump, and doesn't have any noticeable image artifacts in its vicinity.
        x = xvals[mask][idx][27]
        y = yvals[mask][idx][27]
        print('Using x,y = ', x, y)
        image_pos = galsim.PositionD(x, y)
        print('size, mag = ', size[mask][idx][27], mag[mask][idx][27])

        data = galsim.fits.read(image_file, dir=example_data_dir)
        b = galsim.BoundsI(int(x) - 15, int(x) + 16, int(y) - 15, int(y) + 16)
        data_stamp = data[b]

        header = galsim.fits.FitsHeader(image_file, dir=example_data_dir)
        sky_level = header['SKYBRITE']
        data_stamp -= sky_level

        raw_meas = data_stamp.FindAdaptiveMom()
        print('raw_meas = ', raw_meas)
        ref_size = raw_meas.moments_sigma
        ref_shape = raw_meas.observed_shape
        print('ref size: ', ref_size)
        print('ref shape: ', ref_shape)

    except IOError:
        x, y = 1195.64074707, 1276.63427734
        image_pos = galsim.PositionD(x, y)
        b = galsim.BoundsI(int(x) - 15, int(x) + 16, int(y) - 15, int(y) + 16)
        ref_size = 1.80668628216
        ref_shape = galsim.Shear(g1=0.022104322221, g2=-0.130925191715)

    # First the PSFEx model using the wcs_file to get the model is sky coordinates.
    psfex = galsim.des.DES_PSFEx(psfex_file, wcs_file, dir=data_dir)
    psf = psfex.getPSF(image_pos)

    # The getLocalWCS function should return a local WCS
    assert psfex.getLocalWCS(image_pos).isLocal()

    # Draw the postage stamp image
    # Note: the PSF already includes the pixel response, so draw with method 'no_pixel'.
    stamp = psf.drawImage(wcs=wcs.local(image_pos),
                          bounds=b,
                          method='no_pixel')
    print('wcs = ', wcs.local(image_pos))
    meas = stamp.FindAdaptiveMom()
    print('meas = ', meas)
    print('pixel scale = ', stamp.wcs.minLinearScale(image_pos=image_pos))
    print('cf sizes: ', ref_size, meas.moments_sigma)
    print('cf shapes: ', ref_shape, meas.observed_shape)
    # The agreement for a single star is not great of course, not even 2 decimals.
    # Divide by 2 to get agreement at 2 dp.
    numpy.testing.assert_almost_equal(meas.moments_sigma / 2,
                                      ref_size / 2,
                                      decimal=2,
                                      err_msg="PSFEx size doesn't match")
    numpy.testing.assert_almost_equal(meas.observed_shape.g1 / 2,
                                      ref_shape.g1 / 2,
                                      decimal=2,
                                      err_msg="PSFEx shape.g1 doesn't match")
    numpy.testing.assert_almost_equal(meas.observed_shape.g2 / 2,
                                      ref_shape.g2 / 2,
                                      decimal=2,
                                      err_msg="PSFEx shape.g2 doesn't match")

    # Repeat without the wcs_file argument, so the model is in chip coordinates.
    # Also check the functionality where the file is already open.
    with pyfits.open(os.path.join(data_dir, psfex_file)) as hdu_list:
        psfex = galsim.des.DES_PSFEx(hdu_list[1])
    psf = psfex.getPSF(image_pos)

    # In this case, the getLocalWCS function won't return anything useful.
    assert psfex.getLocalWCS(image_pos) is None

    # Draw the postage stamp image.  This time in image coords, so pixel_scale = 1.0.
    stamp = psf.drawImage(bounds=b, scale=1.0, method='no_pixel')
    meas = stamp.FindAdaptiveMom()
    numpy.testing.assert_almost_equal(
        meas.moments_sigma / 2,
        ref_size / 2,
        decimal=2,
        err_msg="no-wcs PSFEx size doesn't match")
    numpy.testing.assert_almost_equal(
        meas.observed_shape.g1 / 2,
        ref_shape.g1 / 2,
        decimal=2,
        err_msg="no-wcs PSFEx shape.g1 doesn't match")
    numpy.testing.assert_almost_equal(
        meas.observed_shape.g2 / 2,
        ref_shape.g2 / 2,
        decimal=2,
        err_msg="no-wcs PSFEx shape.g2 doesn't match")

    # Now the shapelet PSF model.  This model is already in sky coordinates, so no wcs_file needed.
    fitpsf = galsim.des.DES_Shapelet(os.path.join(data_dir, fitpsf_file))
    psf = fitpsf.getPSF(image_pos)

    # Draw the postage stamp image
    # Again, the PSF already includes the pixel response.
    stamp = psf.drawImage(wcs=wcs.local(image_pos),
                          bounds=b,
                          method='no_pixel')
    meas = stamp.FindAdaptiveMom()
    numpy.testing.assert_almost_equal(
        meas.moments_sigma / 2,
        ref_size / 2,
        decimal=2,
        err_msg="Shapelet PSF size doesn't match")
    numpy.testing.assert_almost_equal(
        meas.observed_shape.g1 / 2,
        ref_shape.g1 / 2,
        decimal=2,
        err_msg="Shapelet PSF shape.g1 doesn't match")
    numpy.testing.assert_almost_equal(
        meas.observed_shape.g2 / 2,
        ref_shape.g2 / 2,
        decimal=2,
        err_msg="Shapelet PSF shape.g2 doesn't match")
Beispiel #23
0
def test_psf_config():
    """Test building the two PSF types using the config layer.
    """
    data_dir = 'des_data'
    psfex_file = "DECam_00154912_12_psfcat.psf"
    fitpsf_file = "DECam_00154912_12_fitpsf.fits"
    wcs_file = "DECam_00154912_12_header.fits"

    image_pos = galsim.PositionD(123.45, 543.21)

    config = {
        'input': {
            'des_shapelet': {
                'dir': data_dir,
                'file_name': fitpsf_file
            },
            'des_psfex': [
                {
                    'dir': data_dir,
                    'file_name': psfex_file
                },
                {
                    'dir': data_dir,
                    'file_name': psfex_file,
                    'image_file_name': wcs_file
                },
            ]
        },
        'psf1': {
            'type': 'DES_Shapelet'
        },
        'psf2': {
            'type': 'DES_PSFEx',
            'num': 0
        },
        'psf3': {
            'type': 'DES_PSFEx',
            'num': 1
        },
        'psf4': {
            'type': 'DES_Shapelet',
            'image_pos': galsim.PositionD(567, 789),
            'flux': 179,
            'gsparams': {
                'folding_threshold': 1.e-4
            }
        },
        'psf5': {
            'type': 'DES_PSFEx',
            'image_pos': galsim.PositionD(789, 567),
            'flux': 388,
            'gsparams': {
                'folding_threshold': 1.e-4
            }
        },

        # This would normally be set by the config processing.  Set it manually here.
        'image_pos': image_pos,
    }

    galsim.config.ProcessInput(config)

    psf1a = galsim.config.BuildGSObject(config, 'psf1')[0]
    fitpsf = galsim.des.DES_Shapelet(fitpsf_file, dir=data_dir)
    psf1b = fitpsf.getPSF(image_pos)
    gsobject_compare(psf1a, psf1b)

    psf2a = galsim.config.BuildGSObject(config, 'psf2')[0]
    psfex0 = galsim.des.DES_PSFEx(psfex_file, dir=data_dir)
    psf2b = psfex0.getPSF(image_pos)
    gsobject_compare(psf2a, psf2b)

    psf3a = galsim.config.BuildGSObject(config, 'psf3')[0]
    psfex1 = galsim.des.DES_PSFEx(psfex_file, wcs_file, dir=data_dir)
    psf3b = psfex1.getPSF(image_pos)
    gsobject_compare(psf3a, psf3b)

    gsparams = galsim.GSParams(folding_threshold=1.e-4)
    psf4a = galsim.config.BuildGSObject(config, 'psf4')[0]
    psf4b = fitpsf.getPSF(galsim.PositionD(567, 789),
                          gsparams=gsparams).withFlux(179)
    gsobject_compare(psf4a, psf4b)

    # Insert a wcs for thes last one.
    config['wcs'] = galsim.FitsWCS(os.path.join(data_dir, wcs_file))
    del config['input_objs']
    galsim.config.ProcessInput(config)
    psfex2 = galsim.des.DES_PSFEx(psfex_file, dir=data_dir, wcs=config['wcs'])
    psf5a = galsim.config.BuildGSObject(config, 'psf5')[0]
    psf5b = psfex2.getPSF(galsim.PositionD(789, 567),
                          gsparams=gsparams).withFlux(388)
    gsobject_compare(psf5a, psf5b)
Beispiel #24
0
def main(argv):

    root = 'DECam_00154912'

    data_dir = 'des_data'

    if not os.path.exists(data_dir):
        print('You will need to download some DES data to use this script.')
        print('Run the following commands from the directory GalSim/examples/des:')
        print()
        print('    wget http://www.sas.upenn.edu/~mjarvis/des_data.tar.gz')
        print('    tar xfz des_data.tar.gz')
        print()
        print('Then try running this script again.  It should work now.')
        sys.exit()

    # Set which chips to run on
    first_chip = 1
    last_chip = 62
    #first_chip = 12
    #last_chip = 12

    # quick and dirty command line parsing.
    for var in argv:
        if var.startswith('first='): first_chip = int(var[6:])
        if var.startswith('last='): last_chip = int(var[5:])
    print('Processing chips %d .. %d'%(first_chip, last_chip))

    out_dir = 'output'

    # The random seed, so the results are deterministic
    random_seed = 1339201

    x_col = 'X_IMAGE'
    y_col = 'Y_IMAGE'
    flux_col = 'FLUX_AUTO'
    flag_col = 'FLAGS'

    xsize_key = 'NAXIS1'
    ysize_key = 'NAXIS2'
    sky_level_key = 'SKYBRITE'
    sky_sigma_key = 'SKYSIGMA'

    # Make output directory if not already present.
    if not os.path.isdir(out_dir):
        os.mkdir(out_dir)

    for chipnum in range(first_chip,last_chip+1):
        print('Start chip ',chipnum)

        # Setup the file names
        image_file = '%s_%02d.fits.fz'%(root,chipnum)
        cat_file = '%s_%02d_cat.fits'%(root,chipnum)
        psfex_file = '%s_%02d_psfcat.psf'%(root,chipnum)
        fitpsf_file = '%s_%02d_fitpsf.fits'%(root,chipnum)
        psfex_image_file = '%s_%02d_psfex_image.fits'%(root,chipnum)
        fitpsf_image_file = '%s_%02d_fitpsf_image.fits'%(root,chipnum)

        # Get some parameters about the image from the data image header information
        image_header = galsim.FitsHeader(image_file, dir=data_dir)
        xsize = image_header[xsize_key]
        ysize = image_header[ysize_key]
        sky_sigma = image_header[sky_sigma_key]  # This is sqrt(variance) / pixel
        sky_level = image_header[sky_level_key]  # This is in ADU / pixel
        gain = sky_level / sky_sigma**2  # an approximation, since gain is missing.

        # Read the WCS
        wcs = galsim.FitsWCS(header=image_header)

        # Setup the images:
        psfex_image = galsim.Image(xsize, ysize, wcs=wcs)
        fitpsf_image = galsim.Image(xsize, ysize, wcs=wcs)

        # Read the other input files
        cat = galsim.Catalog(cat_file, hdu=2, dir=data_dir)
        psfex = galsim.des.DES_PSFEx(psfex_file, image_file, dir=data_dir)
        fitpsf = galsim.des.DES_Shapelet(fitpsf_file, dir=data_dir)

        nobj = cat.nobjects
        print('Catalog has ',nobj,' objects')

        for k in range(nobj):
            sys.stdout.write('.')
            sys.stdout.flush()

            # Skip objects with a non-zero flag
            flag = cat.getInt(k,flag_col)
            if flag: continue

            # Get the position from the galaxy catalog
            x = cat.getFloat(k,x_col)
            y = cat.getFloat(k,y_col)
            image_pos = galsim.PositionD(x,y)
            #print '    pos = ',image_pos
            x += 0.5   # + 0.5 to account for even-size postage stamps
            y += 0.5
            ix = int(math.floor(x+0.5))  # round to nearest pixel
            iy = int(math.floor(y+0.5))
            dx = x-ix
            dy = y-iy
            offset = galsim.PositionD(dx,dy)

            # Also get the flux of the galaxy from the catalog
            flux = cat.getFloat(k,flux_col)
            #print '    flux = ',flux
            #print '    wcs = ',wcs.local(image_pos)

            # First do the PSFEx image:
            if True:
                # Define the PSF profile
                psf = psfex.getPSF(image_pos).withFlux(flux)
                #print '    psfex psf = ',psf

                # Draw the postage stamp image
                # Note: Use no_pixel method, since the PSFEx estimate of the PSF already includes
                # the pixel response.
                stamp = psf.drawImage(wcs=wcs.local(image_pos), offset=offset, method='no_pixel')

                # Recenter the stamp at the desired position:
                stamp.setCenter(ix,iy)

                # Find overlapping bounds
                bounds = stamp.bounds & psfex_image.bounds
                psfex_image[bounds] += stamp[bounds]


            # Next do the ShapeletPSF image:
            # If the position is not within the interpolation bounds, fitpsf will
            # raise an exception telling us to skip this object.  Easier to check here.
            if fitpsf.bounds.includes(image_pos):
                # Define the PSF profile
                psf = fitpsf.getPSF(image_pos).withFlux(flux)
                #print '    fitpsf psf = ',psf

                # Draw the postage stamp image
                # Again, the PSF already includes the pixel response.
                stamp = psf.drawImage(wcs=wcs.local(image_pos), offset=offset, method='no_pixel')

                # Recenter the stamp at the desired position:
                stamp.setCenter(ix,iy)

                # Find overlapping bounds
                bounds = stamp.bounds & fitpsf_image.bounds
                fitpsf_image[bounds] += stamp[bounds]
            else:
                pass
                #print '...not in fitpsf.bounds'
        print()

        # Add background level
        psfex_image += sky_level
        fitpsf_image += sky_level

        # Add noise
        rng = galsim.BaseDeviate(random_seed)
        noise = galsim.CCDNoise(rng, gain=gain)
        psfex_image.addNoise(noise)
        # Reset the random seed to match the action of the yaml version
        # Note: the difference between seed and reset matters here.
        # reset would sever the connection between this rng instance and the one stored in noise.
        # seed changes the seed while keeping the connection between them.
        rng.seed(random_seed)
        fitpsf_image.addNoise(noise)

        # Now write the images to disk.
        psfex_image.write(psfex_image_file, dir=out_dir)
        fitpsf_image.write(fitpsf_image_file, dir=out_dir)
        print('Wrote images to %s and %s'%(
                os.path.join(out_dir,psfex_image_file),
                os.path.join(out_dir,fitpsf_image_file)))

        # Increment the random seed by the number of objects in the file
        random_seed += nobj
Beispiel #25
0
# We make new seg files now, so use out_dir for those paths as well.  But don't copy the originals.
seg_path = [ os.path.join(out_dir,os.path.basename(file)) for file in seg_path ]
src_cols[0] = list(out_path[1:])
src_cols[1] = list(sky_path[1:])
src_cols[2] = list(seg_path[1:])
src_rows = zip(*src_cols)
out_src_file = os.path.join(out_dir,os.path.basename(coadd_srclist))
with open(out_src_file,'w') as out_src:
    for row in src_rows:
        out_src.write('%s %s %s %s\n'%(row))

# Read the image files and make blank ones.
# In principal, we could read the files and get the bounds from that, but 
# that's slow.  So we just use the known bounds and use that for everything.
se_bounds = galsim.BoundsI(1,2048,1,4096)
image_wcs = [ galsim.FitsWCS(file_name) for file_name in image_path ]
images = [ galsim.Image(wcs=wcs, bounds=se_bounds) for wcs in image_wcs ]
# Except the first one (the coadd image) is different
coadd_bounds = galsim.BoundsI(1,10000,1,10000)
images[0] = galsim.Image(wcs=image_wcs[0], bounds=coadd_bounds)
print 'Initialized the blank images'

# Setup a PSF that varies according to a second order function across the image
# Each chip will have its own PSF functions for size, e1, e2.
# size = 0.9 arcsec + 0.2 arcsec * F_size(x,y)
# e1 = 0.05 * F_e1(x,y)
# e2 = 0.05 * F_e2(x,y)
# where each F has the form: a + b T1(x) + c T1(y) + d T2(x) + e T1(x) T1(y) + f T2(y)
# Similar for e1, e2.  So need 18 parameters.  Each parameter is chosen to 
# fall between -1 and 1, and the polynomial factors are Chebyshev polynomials
# using the appropriate bounds (different for x,y) also vary between -1 and 1.
Beispiel #26
0
def read_image_header(img_file):
    """Read some information from the image header.

    Returns (date, time, filter, ccdnum, detpos, telra, teldec, ha, 
             airmass, sky, sigsky, fwhm, tiling, hex, wcs)
    """
    print 'Start read_image_header'
    print img_file
    import galsim
    import astropy.io.fits as pyfits

    if img_file.endswith('fz'):
        hdu = 1
    else:
        hdu = 0

    # fitsio is a bit faster here.  11 sec/exp rather than 12, so not a huge difference, but still.
    with pyfits.open(img_file) as pyf:
        #print pyf
        #print pyf[hdu]
        h = pyf[hdu].header
        #h = pyf[hdu].read_header()
        #print 'opened'
        # DATE-OBS looks like '2012-12-03T07:38:54.174780', so split on T.
        date = h['DATE-OBS']
        date, time = date.strip().split('T', 1)

        # FILTER looks like 'z DECam SDSS c0004 9260.0 1520.0', so split on white space
        filter = h['FILTER']
        filter = filter.split()[0]

        # CCDNUM is 1-62.  DETPOS is a string such as 'S29     '.  Strip off the whitespace.
        ccdnum = h['CCDNUM']
        ccdnum = int(ccdnum)
        detpos = h['DETPOS']
        detpos = detpos.strip()
        #print 'detpos = ',detpos

        # TELRA, TELDEC look like '-62:30:22.320'.  Use GalSim to convert to decimal degrees.
        telra = h['TELRA']
        teldec = h['TELDEC']
        telra = galsim.HMS_Angle(telra) / galsim.degrees
        teldec = galsim.DMS_Angle(teldec) / galsim.degrees
        #print 'telra, teldec = ',telra,teldec

        # HA looks like '03:12:02.70''.  Use GalSim to convert to decimal degrees.
        ha = h['HA']
        ha = galsim.HMS_Angle(ha) / galsim.degrees

        # A few more items to grab from the header, but allow default values for these:
        airmass = float(h.get('AIRMASS', -999))
        sky = float(h.get('SKYBRITE', -999))
        sigsky = float(h.get('SKYSIGMA', -999))
        fwhm = float(h.get('FWHM', -999))

        tiling = int(h.get('TILING', 0))
        hex = int(h.get('HEX', 0))

        # Use Galsim to read WCS
        wcs = galsim.FitsWCS(header=h)
        #print 'wcs = ',wcs

    return (date, time, filter, ccdnum, detpos, telra, teldec, ha, airmass,
            sky, sigsky, fwhm, tiling, hex, wcs)
Beispiel #27
0
    def analyse1(
        self,
        central_data,
        neighbour_data,
        nreal=1000
    ):  #, central_ellipticity, dneigh=20, central_flux=1912.0, psf_size=3.7, neighbour_flux=1912.0, neighbour_size=3.2, nrealisations=1000):
        # Level 1 - loop over SNR
        #-----------------------------------------------------------------------

        # Initialise the random number generator
        np.random.seed(self.random_seed)

        self.object_mask = np.loadtxt("mask_template.txt")

        m = {}
        m[1] = []
        m[2] = []
        c = {}
        c[1] = []
        c[2] = []
        snr = []

        # Setup a dummy wcs
        # We load it here to avoid too much unncessary io
        # In fact it should provide a skeleton only, since we overwrite the Jacobian with an identity matrix
        wcs_path = "/share/des/disc2/y1/OPS/coadd/20141118000051_DES0014-4414/coadd/DES0014-4414_r.fits.fz"
        orig_col = 1000
        orig_row = 1000
        image_pos = galsim.PositionD(orig_col, orig_row)
        self.wcs = galsim.FitsWCS(wcs_path)
        self.opt = p3s.Options(
            "/home/samuroff/shear_pipeline/end-to-end/end-to-end_code/config_files/im3shape/params_disc.ini"
        )

        self.binning = np.logspace(1, 2.8, 12)
        upper = self.binning[1:]
        lower = self.binning[:-1]

        # Cycle over the central flux, as a proxy for SNR
        for i, limits in enumerate(zip(lower, upper)):
            snr_min = limits[0]
            snr_max = limits[1]
            print "Level 1 iteration: %d SNR = %3.3f - %3.3f" % (
                i + 1, snr_min, snr_max)
            # Selection function for this bin
            sel = (central_data.res["snr"] >
                   snr_min) & (central_data.res["snr"] < snr_max)

            print "Will do %d realisations for this bin:" % nreal

            De1 = []
            De2 = []
            sn = []
            g1 = []
            g2 = []
            for j in xrange(nreal):
                print "%d/%d" % (j + 1, nreal)
                self.generate_central_realisation(central_data, sel)
                self.generate_neighbour_realisation(neighbour_data,
                                                    central_data, sel)

                # Draw this neighbour realisation repeatedly on a ring of angular positions
                snr, e1, e2 = self.do_position_loop()

                sn.append(snr)
                De1.append(e1)
                De2.append(e2)
                g1.append(self.g[0])
                g2.append(self.g[1])

            data = np.zeros(len(g1),
                            dtype=[("e1", float), ("e2", float),
                                   ("true_g1", float), ("true_g2", float)])
            data["e1"], data["e2"] = np.array(De1), np.array(De2)
            data["true_g1"], data["true_g2"] = np.array(g1), np.array(g2)

            bias = di.get_bias(data,
                               nbins=5,
                               names=["m11", "m22", "c11", "c22"],
                               binning="equal_number",
                               silent=True)
            print bias

            m[1].append(bias["m11"][0])
            m[2].append(bias["m22"][0])
            c[1].append(bias["c11"][0])
            c[2].append(bias["c22"][0])

        import pdb
        pdb.set_trace()

        print "Done all loops"
Beispiel #28
0
def setup_simple(boxsize=32,
                 model="disc",
                 upsample=1,
                 size=2,
                 flux=None,
                 shear=(0, 0),
                 neighbour=[np.inf, np.inf],
                 neighbour_size=2.0,
                 neighbour_flux=0.13,
                 neighbour_ellipticity=(0, 0),
                 psf_ellipticity=(0, 0),
                 psf_size=0.1,
                 wcs=None,
                 opt=None):
    """Basic function to construct a test galaxy for exploring shape biases."""

    if opt is None:
        opt = p3s.Options(
            "/home/samuroff/shear_pipeline/end-to-end/end-to-end_code/config_files/im3shape/params_disc.ini"
        )

    opt.stamp_size = boxsize

    psfsize = (boxsize +
               opt._struct.contents.padding) * opt._struct.contents.upsampling
    upsampling = opt._struct.contents.upsampling

    large_boxsize = boxsize * 7

    gal1 = get_model(size=size,
                     type=model,
                     g1=shear[0],
                     g2=shear[1],
                     flux=flux)
    pos1 = galsim.PositionD(0, 0)

    # Add a tiny nominal PSF
    psf, psf_image = get_fixed_gaussian_psf(opt, psf_size, psf_ellipticity[0],
                                            psf_ellipticity[1], wcs)
    #import pdb ; pdb.set_trace()
    #galsim.Gaussian(fwhm=psf_size*0.27)

    if wcs is None:
        wcs_path = "/share/des/disc2/y1/OPS/coadd/20141118000051_DES0014-4414/coadd/DES0014-4414_r.fits.fz"
        wcs = galsim.FitsWCS(wcs_path)
    orig_col = 1000
    orig_row = 1000
    image_pos = galsim.PositionD(orig_col, orig_row)
    local_wcs = wcs.local(image_pos)

    local_wcs._dudx = 1.0
    local_wcs._dudy = 0.0
    local_wcs._dvdx = 0.0
    local_wcs._dvdy = 1.0
    A = np.array([[local_wcs._dudx, local_wcs._dudy],
                  [local_wcs._dvdx, local_wcs._dvdy]])
    local_wcs._det = np.linalg.det(A)

    pix = wcs.toWorld(galsim.Pixel(0.27), image_pos=image_pos)

    obj1 = galsim.Convolve([gal1, psf, pix])

    im1 = obj1.drawImage(wcs=local_wcs,
                         nx=large_boxsize,
                         ny=large_boxsize,
                         method='no_pixel')
    im3 = obj1.drawImage(wcs=local_wcs,
                         nx=large_boxsize,
                         ny=large_boxsize,
                         method='no_pixel')

    # And a neighbouring object if specified
    if np.isfinite(np.array(neighbour)).all():
        print "drawing neighbour at (%d, %d)" % (int(
            neighbour[0]), int(neighbour[1]))
        gal2 = galsim.Sersic(n=1, half_light_radius=neighbour_size)
        gal2 = gal2.withFlux(neighbour_flux)
        nshear = galsim.Shear(g1=neighbour_ellipticity[0],
                              g2=neighbour_ellipticity[1])
        gal2 = gal2.shear(nshear)

        obj2 = galsim.Convolve([gal2, psf, pix])

        pos2 = galsim.PositionD(x=neighbour[0], y=neighbour[1])

        im2 = obj2.drawImage(wcs=local_wcs,
                             nx=large_boxsize,
                             ny=large_boxsize,
                             method='no_pixel',
                             offset=pos2)

        im3 += im2.array

    trim = (large_boxsize - boxsize) / 2.
    lim = galsim.BoundsI(xmin=trim,
                         xmax=large_boxsize - trim - 1,
                         ymin=trim,
                         ymax=large_boxsize - trim - 1)

    del (wcs)
    gc.collect()

    return im3[lim].array, psf_image