def test_edge_on():
    """ Test that an edge-on profile looks similar to an almost-edge-on profile, and doesn't crash.
    """

    scale_radius = 3.0

    inclinations = (np.arccos(0.01),2*np.pi-np.arccos(0.01),np.pi/2.)

    images = []

    for inclination in inclinations:
        # Set up the profile
        prof = galsim.InclinedExponential(inclination*galsim.radians, scale_radius=scale_radius,
                                          scale_h_over_r=0.1)

        check_basic(prof, "Edge-on InclinedExponential")

        # Draw an image of it
        image = galsim.Image(image_nx,image_ny,scale=1.0)
        prof.drawImage(image)

        # Add it to the list of images
        images.append(image.array)

    # Check they're all almost the same
    np.testing.assert_array_almost_equal(images[1], images[0], decimal=2)
    np.testing.assert_array_almost_equal(images[1], images[2], decimal=2)

    # Also the edge-on version should get the maxSB value exactly right = exp.maxSB * r/h.
    exp = galsim.Exponential(scale_radius=scale_radius)
    np.testing.assert_array_almost_equal(prof.maxSB(), exp.maxSB() / 0.1)
    prof.drawImage(image, method='sb', use_true_center=False)
    print('max pixel: ',image.array.max(),' cf.',prof.maxSB())
    np.testing.assert_allclose(image.array.max(), prof.maxSB(), rtol=0.01)
Exemplo n.º 2
0
def get_prof(mode, *args, **kwargs):
    """Function to get either InclinedExponential or InclinedSersic (with n=1, trunc=0)
       depending on mode
    """
    new_kwargs = deepcopy(kwargs)
    if len(args) > 0:
        new_kwargs["inclination"] = args[0]
    if len(args) > 1:
        new_kwargs["scale_radius"] = args[1]
    if len(args) > 2:
        new_kwargs["scale_height"] = args[2]

    if mode == "InclinedSersic":

        if not "trunc" in new_kwargs:
            new_kwargs["trunc"] = 0.
        if not "n" in new_kwargs:
            new_kwargs["n"] = 1.

        prof = galsim.InclinedSersic(**new_kwargs)
    else:
        if "trunc" in new_kwargs:
            del new_kwargs["trunc"]
        if "n" in new_kwargs:
            del new_kwargs["n"]
        if "flux_untruncated" in new_kwargs:
            del new_kwargs["flux_untruncated"]
        prof = galsim.InclinedExponential(**new_kwargs)

    return prof
def test_k_limits():
    """ Check that the maxk and stepk give reasonable results for a few different profiles. """

    for inc_angle, scale_radius, scale_height in zip(image_inc_angles,image_scale_radii,
                                                     image_scale_heights):
        # Get float values for the details
        inc_angle=float(inc_angle)
        scale_radius=float(scale_radius)
        scale_height=float(scale_height)

        gsparams = galsim.GSParams()

        # Now make a test image
        test_profile = galsim.InclinedExponential(inc_angle*galsim.radians, scale_radius,
                                                  scale_height)

        # Check that the k value at maxK() is below maxk_threshold in both the x and y dimensions
        kx = test_profile.maxK()
        ky = test_profile.maxK()

        kx_value=test_profile.kValue(kx=kx,ky=0.)
        np.testing.assert_(np.abs(kx_value)<gsparams.maxk_threshold,
                           msg="kx_value is not below maxk_threshold: " + str(kx_value) + " >= "
                            + str(gsparams.maxk_threshold))

        ky_value=test_profile.kValue(kx=0.,ky=ky)
        np.testing.assert_(np.abs(ky_value)<gsparams.maxk_threshold,
                           msg="ky_value is not below maxk_threshold: " + str(ky_value) + " >= "
                            + str(gsparams.maxk_threshold))

        # Check that less than folding_threshold fraction of light falls outside r = pi/stepK()
        rmax = np.pi/test_profile.stepK()

        test_image = galsim.Image(int(10*rmax),int(10*rmax),scale=1.0)
        test_profile.drawImage(test_image)

        image_center = test_image.center()

        # Get an array of indices within the limits
        image_shape = np.shape(test_image.array)
        x, y = np.indices(image_shape, dtype=float)

        x -= image_center.x
        y -= image_center.y

        r = np.sqrt(np.square(x)+np.square(y))

        good = r<rmax

        # Get flux within the limits
        contained_flux = np.ravel(test_image.array)[np.ravel(good)].sum()

        # Check that we're not missing too much flux
        total_flux = 1.
        np.testing.assert_((total_flux-contained_flux)/(total_flux)<gsparams.folding_threshold,
                           msg="Too much flux lost due to folding.\nTotal flux = " +
                           str(total_flux) + "\nContained flux = " + str(contained_flux) +
                           "\nLost = " + str((total_flux-contained_flux)/(total_flux)))
Exemplo n.º 4
0
def test_sanity():
    """ Performs various sanity checks on a set of InclinedExponential profiles. """

    print('flux, inc_angle, scale_radius, scale_height, pos_angle')
    for flux, inc_angle, scale_radius, scale_height, pos_angle in zip(fluxes,
                                                                      image_inc_angles,
                                                                      image_scale_radii,
                                                                      image_scale_heights,
                                                                      image_pos_angles):

        # Get float values for the details
        flux = float(flux)
        inc_angle=float(inc_angle)
        scale_radius=float(scale_radius)
        scale_height=float(scale_height)
        pos_angle=float(pos_angle)
        print(flux, inc_angle, scale_radius, scale_height, pos_angle)

        # Now make a test image
        test_profile = galsim.InclinedExponential(inc_angle*galsim.radians, scale_radius,
                                                  scale_height, flux=flux)

        check_basic(test_profile, "InclinedExponential")

        # Check that h/r is properly given by the method and property for it
        np.testing.assert_almost_equal(test_profile.scale_height/test_profile.scale_radius,
                                       test_profile.scale_h_over_r)
        np.testing.assert_almost_equal(test_profile.getScaleHeight()/test_profile.getScaleRadius(),
                                       test_profile.getScaleHOverR())

        # Rotate it by the position angle
        test_profile = test_profile.rotate(pos_angle*galsim.radians)

        # Check that the k value for (0,0) is the flux
        np.testing.assert_almost_equal(test_profile.kValue(kx=0.,ky=0.),flux)

        # Check that the drawn flux for a large image is indeed the flux
        test_image = galsim.Image(5*image_nx,5*image_ny,scale=1.0)
        test_profile.drawImage(test_image)
        test_flux = test_image.array.sum()
        np.testing.assert_almost_equal(test_flux,flux,decimal=3)

        # Check that the centroid is (0,0)
        centroid = test_profile.centroid()
        np.testing.assert_equal(centroid.x, 0.)
        np.testing.assert_equal(centroid.y, 0.)

        # Check maxSB
        # We don't do a great job at estimating this, but it should be in the right ball park,
        # and typically too large.
        test_profile.drawImage(test_image, method='sb', use_true_center=False)
        print('max pixel: ',test_image.array.max(),' cf.',test_profile.maxSB())
        np.testing.assert_allclose(test_image.array.max(), test_profile.maxSB(), rtol=0.3)
        np.testing.assert_array_less(test_image.array.max(), test_profile.maxSB())
Exemplo n.º 5
0
def _make_inclined_disk(src, bbox_num_reff=10, band='i'):
    assert HAS_GALSIM, 'you need galsim to make inclined disks'
    r_pix = src['r_e'] / pixscale
    side = 2 * int(bbox_num_reff * r_pix) + 1
    nx, ny = (side, side)
    incl = src['incl'] * galsim.degrees
    model = galsim.InclinedExponential(incl,
                                       half_light_radius=src['r_e'],
                                       scale_h_over_r=src['q0'])
    model = model.rotate(src['PA'] * galsim.degrees)
    flux = 10**(0.4 * (zpt - src[f'm_{band}']))
    galaxy = model.drawImage(nx=nx, ny=ny, scale=pixscale).array * flux
    return galaxy
def test_regression():
    """Test that the inclined exponential profile matches the results from Lance Miller's code.
       Reference images are provided in the ./inclined_exponential_images directory, as well as
       the code ('hankelcode.c') used to generate them."""

    for inc_angle, scale_radius, scale_height, pos_angle in zip(image_inc_angles,
                                                                image_scale_radii,
                                                                image_scale_heights,
                                                                image_pos_angles):

        image_filename = "galaxy_"+inc_angle+"_"+scale_radius+"_"+scale_height+"_"+pos_angle+".fits"
        image = galsim.fits.read(image_filename, image_dir)

        # Get float values for the details
        inc_angle=float(inc_angle)
        scale_radius=float(scale_radius)
        scale_height=float(scale_height)
        pos_angle=float(pos_angle)

        # Now make a test image
        test_profile = galsim.InclinedExponential(inc_angle*galsim.radians, scale_radius,
                                                  scale_height)
        check_basic(test_profile, "InclinedExponential")

        # Rotate it by the position angle
        test_profile = test_profile.rotate(pos_angle*galsim.radians)

        # Draw it onto an image
        test_image = galsim.Image(image_nx,image_ny,scale=1.0)
        test_profile.drawImage(test_image,offset=(0.5,0.5)) # Offset to match Lance's

        # Compare to the example - Due to the different fourier transforms used, some offset is
        # expected, so we just compare in the core to two decimal places

        image_core = image.array[image_ny//2-2:image_ny//2+3, image_nx//2-2:image_nx//2+3]
        test_image_core = test_image.array[image_ny//2-2:image_ny//2+3, image_nx//2-2:image_nx//2+3]

        ratio_core = image_core / test_image_core

        # galsim.fits.write(test_image,"test_"+image_filename,image_dir)

        np.testing.assert_array_almost_equal(
                ratio_core, np.mean(ratio_core)*np.ones_like(ratio_core),
                decimal = 2,
                err_msg = "Error in comparison of inclined exponential profile to samples.",
                verbose=True)
def test_pickle():
    """ Check that we can pickle it. """

    exp = galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0,
                                     scale_height=0.3)
    do_pickle(exp)
    do_pickle(exp.SBProfile)
    do_pickle(galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0))
    do_pickle(galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0,
                                         scale_h_over_r=0.2))
    do_pickle(galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0,
                                         scale_height=0.3, flux=10.0))
    do_pickle(galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0,
                                         scale_height=0.3,
                                         gsparams=galsim.GSParams(folding_threshold=1.1e-3)))
    do_pickle(galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0,
                                         scale_height=0.3, flux=10.0,
                                         gsparams=galsim.GSParams(folding_threshold=1.1e-3)))
def test_exponential():
    """ Test that it looks identical to an exponential when inclination is zero. """

    scale_radius = 3.0

    # Set up the profiles
    inc_exp_profile = galsim.InclinedExponential(0*galsim.radians, scale_radius=scale_radius,
                                                 scale_height=scale_radius/10.)
    exp_profile = galsim.Exponential(scale_radius=scale_radius)

    # Draw images for both
    inc_exp_image = galsim.Image(image_nx, image_ny, scale=1.0)
    exp_image = galsim.Image(image_nx, image_ny, scale=1.0)

    inc_exp_profile.drawImage(inc_exp_image)
    exp_profile.drawImage(exp_image)

    # Check that they're the same
    np.testing.assert_array_almost_equal(inc_exp_image.array, exp_image.array, decimal=4)

    # The face-on version should get the maxSB value exactly right.
    np.testing.assert_array_almost_equal(inc_exp_profile.maxSB(), exp_profile.maxSB())

    check_basic(inc_exp_profile, "Face-on InclinedExponential")
Exemplo n.º 9
0
    def build_file(seed, file_name, mass, nobj, rng, truth_file_name, halo_id,
                   first_obj_id):
        """A function that does all the work to build a single file.
           Returns the total time taken.
        """
        t1 = time.time()

        # Build the image onto which we will draw the galaxies.
        full_image = galsim.ImageF(image_size, image_size)

        # The "true" center of the image is allowed to be halfway between two pixels, as is the
        # case for even-sized images.  full_image.bounds.center() is an integer position,
        # which would be 1/2 pixel up and to the right of the true center in this case.
        im_center = full_image.bounds.trueCenter()

        # For the WCS, this time we use UVFunction, which lets you define arbitrary u(x,y)
        # and v(x,y) functions.  We use a simple cubic radial function to create a
        # pincushion distortion.  This is a typical kind of telescope distortion, although
        # we exaggerate the magnitude of the effect to make it more apparent.
        # The pixel size in the center of the image is 0.05, but near the corners (r=362),
        # the pixel size is approximately 0.075, which is much more distortion than is
        # normally present in typical telescopes.  But it makes the effect of the variable
        # pixel area obvious when you look at the weight image in the output files.
        ufunc1 = lambda x, y: 0.05 * x * (1. + 2.e-6 * (x**2 + y**2))
        vfunc1 = lambda x, y: 0.05 * y * (1. + 2.e-6 * (x**2 + y**2))

        # It's not required to provide the inverse functions.  However, if we don't, then
        # you will only be able to do toWorld operations, not the inverse toImage.
        # The inverse function does not have to be exact either.  For example, you could provide
        # a function that does some kind of iterative solution to whatever accuracy you care
        # about.  But in this case, we can do the exact inverse.
        #
        # Let w = sqrt(u**2 + v**2) and r = sqrt(x**2 + y**2).  Then the solutions are:
        # x = (u/w) r and y = (u/w) r, and we use Cardano's method to solve for r given w:
        # See http://en.wikipedia.org/wiki/Cubic_function#Cardano.27s_method
        #
        # w = 0.05 r + 2.e-6 * 0.05 * r**3
        # r = 100 * ( ( 5 sqrt(w**2 + 5.e3/27) + 5 w )**(1./3.) -
        #           - ( 5 sqrt(w**2 + 5.e3/27) - 5 w )**(1./3.) )

        def xfunc1(u, v):
            import math
            wsq = u * u + v * v
            if wsq == 0.:
                return 0.
            else:
                w = math.sqrt(wsq)
                temp = 5. * math.sqrt(wsq + 5.e3 / 27)
                r = 100. * ((temp + 5 * w)**(1. / 3.) -
                            (temp - 5 * w)**(1. / 3))
                return u * r / w

        def yfunc1(u, v):
            import math
            wsq = u * u + v * v
            if wsq == 0.:
                return 0.
            else:
                w = math.sqrt(wsq)
                temp = 5. * math.sqrt(wsq + 5.e3 / 27)
                r = 100. * ((temp + 5 * w)**(1. / 3.) -
                            (temp - 5 * w)**(1. / 3))
                return v * r / w

        # You could pass the above functions to UVFunction, and normally we would do that.
        # The only down side to doing so is that the specification of the WCS in the FITS
        # file is rather ugly.  GalSim is able to turn the python byte code into strings,
        # but they are basically a really ugly mess of random-looking characters.  GalSim
        # will be able to read it back in, but human readers will have no idea what WCS
        # function was used.  To see what they look like, uncomment this line and comment
        # out the later wcs line.
        #wcs = galsim.UVFunction(ufunc1, vfunc1, xfunc1, yfunc1, origin=im_center)

        # If you provide the functions as strings, then those strings will be preserved
        # in the FITS header in a form that is more legible to human readers.
        # It also has the extra benefit of matching the output from demo9.yaml, which we
        # always try to do.  The config file has no choice but to specify the functions
        # as strings.

        ufunc = '0.05 * x * (1. + 2.e-6 * (x**2 + y**2))'
        vfunc = '0.05 * y * (1. + 2.e-6 * (x**2 + y**2))'
        xfunc = (
            '( lambda w: ( 0 if w==0 else ' +
            '100.*u/w*(( 5*(w**2 + 5.e3/27.)**0.5 + 5*w )**(1./3.) - ' +
            '( 5*(w**2 + 5.e3/27.)**0.5 - 5*w )**(1./3.))))( (u**2+v**2)**0.5 )'
        )
        yfunc = (
            '( lambda w: ( 0 if w==0 else ' +
            '100.*v/w*(( 5*(w**2 + 5.e3/27.)**0.5 + 5*w )**(1./3.) - ' +
            '( 5*(w**2 + 5.e3/27.)**0.5 - 5*w )**(1./3.))))( (u**2+v**2)**0.5 )'
        )

        # The origin parameter defines where on the image should be considered (x,y) = (0,0)
        # in the WCS functions.
        wcs = galsim.UVFunction(ufunc, vfunc, xfunc, yfunc, origin=im_center)

        # Assign this wcs to full_image
        full_image.wcs = wcs

        # The weight image will hold the inverse variance for each pixel.
        # We can set the wcs directly on construction with the wcs parameter.
        weight_image = galsim.ImageF(image_size, image_size, wcs=wcs)

        # It is common for astrometric images to also have a bad pixel mask.  We don't have any
        # defect simulation currently, so our bad pixel masks are currently all zeros.
        # But someday, we plan to add defect functionality to GalSim, at which point, we'll
        # be able to mark those defects on a bad pixel mask.
        # Note: the S in ImageS means to use "short int" for the data type.
        # This is a typical choice for a bad pixel image.
        badpix_image = galsim.ImageS(image_size, image_size, wcs=wcs)

        # We also draw a PSF image at the location of every galaxy.  This isn't normally done,
        # and since some of the PSFs overlap, it's not necessarily so useful to have this kind
        # of image.  But in this case, it's fun to look at the psf image, especially with
        # something like log scaling in ds9 to see how crazy an aberrated OpticalPSF with
        # struts can look when there is no atmospheric component to blur it out.
        psf_image = galsim.ImageF(image_size, image_size, wcs=wcs)

        # We will also write some truth information to an output catalog.
        # In real simulations, it is often useful to have a catalog of the truth values
        # to compare to measurements either directly or as cuts on the galaxy sample to
        # find where systematic errors are largest.
        # For now, we just make an empty OutputCatalog object with the names and types of the
        # columns.
        names = [
            'object_id', 'halo_id', 'flux', 'radius', 'h_over_r',
            'inclination.rad', 'theta.rad', 'mu', 'redshift', 'shear.g1',
            'shear.g2', 'pos.x', 'pos.y', 'image_pos.x', 'image_pos.y',
            'halo_mass', 'halo_conc', 'halo_redshift'
        ]
        types = [
            int, int, float, float, float, float, float, float, float, float,
            float, float, float, float, float, float, float, float
        ]
        truth_cat = galsim.OutputCatalog(names, types)

        # Setup the NFWHalo stuff:
        nfw = galsim.NFWHalo(mass=mass,
                             conc=nfw_conc,
                             redshift=nfw_z_halo,
                             omega_m=omega_m,
                             omega_lam=omega_lam)
        # Note: the last two are optional.  If they are omitted, then (omega_m=0.3, omega_lam=0.7)
        # are actually the defaults.  If you only specify one of them, the other is set so that
        # the total is 1.  But you can define both values so that the total is not 1 if you want.
        # Radiation is assumed to be zero and dark energy equation of state w = -1.
        # If you want to include either radiation or more complicated dark energy models,
        # you can define your own cosmology class that defines the functions a(z), E(a), and
        # Da(z_source, z_lens).  Then you can pass this to NFWHalo as a `cosmo` parameter.

        # Make the PSF profile outside the loop to minimize the (significant) OpticalPSF
        # construction overhead.
        psf = galsim.OpticalPSF(lam=psf_lam,
                                diam=psf_D,
                                obscuration=psf_obsc,
                                nstruts=psf_nstruts,
                                strut_thick=psf_strut_thick,
                                strut_angle=psf_strut_angle,
                                defocus=psf_defocus,
                                astig1=psf_astig1,
                                astig2=psf_astig2,
                                coma1=psf_coma1,
                                coma2=psf_coma2,
                                trefoil1=psf_trefoil1,
                                trefoil2=psf_trefoil2)

        for k in range(nobj):

            # Initialize the random number generator we will be using for this object:
            ud = galsim.UniformDeviate(seed + k + 1)

            # Determine where this object is going to go.
            # We choose points randomly within a donut centered at the center of the main image
            # in order to avoid placing galaxies too close to the halo center where the lensing
            # is not weak.  We use an inner radius of 3 arcsec and an outer radius of 12 arcsec,
            # which takes us essentially to the edge of the image.
            radius = 12
            inner_radius = 3
            max_rsq = radius**2
            min_rsq = inner_radius**2
            while True:  # (This is essentially a do..while loop.)
                x = (2. * ud() - 1) * radius
                y = (2. * ud() - 1) * radius
                rsq = x**2 + y**2
                if rsq >= min_rsq and rsq <= max_rsq: break
            pos = galsim.PositionD(x, y)

            # We also need the position in pixels to determine where to place the postage
            # stamp on the full image.
            image_pos = wcs.toImage(pos)

            # For even-sized postage stamps, the nominal center (returned by stamp.bounds.center())
            # cannot be at the true center (returned by stamp.bounds.trueCenter()) of the postage
            # stamp, since the nominal center values have to be integers.  Thus, the nominal center
            # is 1/2 pixel up and to the right of the true center.
            # If we used odd-sized postage stamps, we wouldn't need to do this.
            x_nominal = image_pos.x + 0.5
            y_nominal = image_pos.y + 0.5

            # Get the integer values of these which will be the actual nominal center of the
            # postage stamp image.
            ix_nominal = int(math.floor(x_nominal + 0.5))
            iy_nominal = int(math.floor(y_nominal + 0.5))

            # The remainder will be accounted for in an offset when we draw.
            dx = x_nominal - ix_nominal
            dy = y_nominal - iy_nominal
            offset = galsim.PositionD(dx, dy)

            # Draw the flux from a power law distribution: N(f) ~ f^-1.5
            # For this, we use the class DistDeviate which can draw deviates from an arbitrary
            # probability distribution.  This distribution can be defined either as a functional
            # form as we do here, or as tabulated lists of x and p values, from which the
            # function is interpolated.
            flux_dist = galsim.DistDeviate(ud,
                                           function=lambda x: x**-1.5,
                                           x_min=gal_flux_min,
                                           x_max=gal_flux_max)
            flux = flux_dist()

            # We introduce here another surface brightness profile, called InclinedExponential.
            # It represents a typical 3D galaxy disk profile inclined at an arbitrary angle
            # relative to face on.
            #
            #     inclination =  0 degrees corresponds to a face-on disk, which is equivalent to
            #                             the regular Exponential profile.
            #     inclination = 90 degrees corresponds to an edge-on disk.
            #
            # A random orientation corresponds to the inclination angle taking the probability
            # distribution:
            #
            #     P(inc) = 0.5 sin(inc)
            #
            # so we again use a DistDeviate to generate these values.
            inc_dist = galsim.DistDeviate(ud,
                                          function=lambda x: 0.5 * math.sin(x),
                                          x_min=0,
                                          x_max=math.pi)
            inclination = inc_dist() * galsim.radians

            # The parameters scale_radius and scale_height give the scale distances in the
            # 3D distribution:
            #
            #     I(R,z) = I_0 / (2 scale_height) * sech^2(z/scale_height) * exp(-r/scale_radius)
            #
            # These values can be given separately if desired.  However, it is often easier to
            # give the ratio scale_h_over_r as an independent value, since the radius and height
            # values are correlated, while h/r is approximately independent of h or r.
            h_over_r = ud() * (gal_h_over_r_max -
                               gal_h_over_r_min) + gal_h_over_r_min

            radius = ud() * (gal_r_max - gal_r_min) + gal_r_min

            # The inclination is around the x-axis, so we want to rotate the galaxy by a
            # random angle.
            theta = ud() * math.pi * 2. * galsim.radians

            # Make the galaxy profile with these values:
            gal = galsim.InclinedExponential(scale_radius=radius,
                                             scale_h_over_r=h_over_r,
                                             inclination=inclination,
                                             flux=flux)
            gal = gal.rotate(theta)

            # Now apply the appropriate lensing effects for this position from
            # the NFW halo mass.
            try:
                g1, g2 = nfw.getShear(pos, nfw_z_source)
                nfw_shear = galsim.Shear(g1=g1, g2=g2)
            except:
                # This shouldn't happen, since we exclude the inner 10 arcsec, but it's a
                # good idea to use the try/except block here anyway.
                import warnings
                warnings.warn(
                    "Warning: NFWHalo shear is invalid -- probably strong lensing!  "
                    + "Using shear = 0.")
                nfw_shear = galsim.Shear(g1=0, g2=0)

            nfw_mu = nfw.getMagnification(pos, nfw_z_source)
            if nfw_mu < 0:
                import warnings
                warnings.warn(
                    "Warning: mu < 0 means strong lensing!  Using mu=25.")
                nfw_mu = 25
            elif nfw_mu > 25:
                import warnings
                warnings.warn(
                    "Warning: mu > 25 means strong lensing!  Using mu=25.")
                nfw_mu = 25

            # Calculate the total shear to apply
            # Since shear addition is not commutative, it is worth pointing out that
            # the order is in the sense that the second shear is applied first, and then
            # the first shear.  i.e. The field shear is taken to be behind the cluster.
            # Kind of a cosmic shear contribution between the source and the cluster.
            # However, this is not quite the same thing as doing:
            #     gal.shear(field_shear).shear(nfw_shear)
            # since the shear addition ignores the rotation that would occur when doing the
            # above lines.  This is normally ok, because the rotation is not observable, but
            # it is worth keeping in mind.
            total_shear = nfw_shear + field_shear

            # Apply the magnification and shear to the galaxy
            gal = gal.magnify(nfw_mu)
            gal = gal.shear(total_shear)

            # Build the final object
            final = galsim.Convolve([psf, gal])

            # Draw the stamp image
            # To draw the image at a position other than the center of the image, you can
            # use the offset parameter, which applies an offset in pixels relative to the
            # center of the image.
            # We also need to provide the local wcs at the current position.
            local_wcs = wcs.local(image_pos)
            stamp = final.drawImage(wcs=local_wcs, offset=offset)

            # Recenter the stamp at the desired position:
            stamp.setCenter(ix_nominal, iy_nominal)

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

            # Also draw the PSF
            psf_stamp = galsim.ImageF(
                stamp.bounds)  # Use same bounds as galaxy stamp
            psf.drawImage(psf_stamp, wcs=local_wcs, offset=offset)
            psf_image[bounds] += psf_stamp[bounds]

            # Add the truth information for this object to the truth catalog
            row = ((first_obj_id + k), halo_id, flux, radius, h_over_r,
                   inclination.rad(), theta.rad(), nfw_mu, nfw_z_source,
                   total_shear.g1, total_shear.g2, pos.x, pos.y, image_pos.x,
                   image_pos.y, mass, nfw_conc, nfw_z_halo)
            truth_cat.addRow(row)

        # Add Poisson noise to the full image
        # Note: The normal calculation of Poission noise isn't quite correct right now.
        # The pixel area is variable, which means the amount of sky flux that enters each
        # pixel is also variable.  The wcs classes have a function `makeSkyImage` which
        # will fill an image with the correct amount of sky flux given the sky level
        # in units of ADU/arcsec^2.  We use the weight image as our work space for this.
        wcs.makeSkyImage(weight_image, sky_level)

        # Add this to the current full_image (temporarily).
        full_image += weight_image

        # Add Poisson noise, given the current full_image.
        # The config parser uses a different random number generator for file-level and
        # image-level values than for the individual objects.  This makes it easier to
        # parallelize the calculation if desired.  In fact, this is why we've been adding 1
        # to each seed value all along.  The seeds for the objects take the values
        # random_seed+1 .. random_seed+nobj.  The seed for the image is just random_seed,
        # which we built already (below) when we calculated how many objects need to
        # be in each file.  Use the same rng again here, since this is also at image scope.
        full_image.addNoise(galsim.PoissonNoise(rng))

        # Subtract the sky back off.
        full_image -= weight_image

        # The weight image is nominally the inverse variance of the pixel noise.  However, it is
        # common to exclude the Poisson noise from the objects themselves and only include the
        # noise from the sky photons.  The variance of the noise is just the sky level, which is
        # what is currently in the weight_image.  (If we wanted to include the variance from the
        # objects too, then we could use the full_image before we added the PoissonNoise to it.)
        # So all we need to do now is to invert the values in weight_image.
        weight_image.invertSelf()

        # Write the file to disk:
        galsim.fits.writeMulti(
            [full_image, badpix_image, weight_image, psf_image], file_name)

        # And write the truth catalog file
        truth_cat.write(truth_file_name)

        t2 = time.time()
        return t2 - t1
Exemplo n.º 10
0
def draw_neighbor(neighbors_config=None, psf=None):
    gsparams = None
    if gsparams is None:
        gsparams = galsim.GSParams(maximum_fft_size=10240)

    #begin of possible kwargsneigh

    profile_type = neighbors_config['profile_type']
    tru_g1 = neighbors_config['tru_g1']
    tru_g2 = neighbors_config['tru_g2']

    if (profile_type == "Sersic"):
        sersiccut = neighbors_config['Sersic']['sersiccut']
        tru_rad = neighbors_config['Sersic']['tru_rad']
        tru_sersicn = neighbors_config['Sersic']['tru_sersicn']
        tru_sb = neighbors_config['Sersic']['tru_sb']
        tru_flux = np.pi * tru_rad * tru_rad * tru_sb

        if sersiccut is None:
            trunc = 0
        else:
            trunc = tru_rad * sersiccut

        gal = galsim.Sersic(n=tru_sersicn,
                            half_light_radius=tru_rad,
                            flux=tru_flux,
                            gsparams=gsparams,
                            trunc=trunc)
        # We make this profile elliptical
        gal = gal.shear(g1=tru_g1,
                        g2=tru_g2)  # This adds the ellipticity to the galaxy

    elif profile_type == "Gaussian":
        tru_flux = neighbors_config['Gaussian']['tru_flux']
        tru_sigma = neighbors_config['Gaussian']['tru_sigma']

        gal = galsim.Gaussian(flux=tru_flux,
                              sigma=tru_sigma,
                              gsparams=gsparams)
        # We make this profile elliptical
        gal = gal.shear(g1=tru_g1,
                        g2=tru_g2)  # This adds the ellipticity to the galaxy

    elif profile_type == 'EBulgeDisk':
        # A more advanced Bulge + Disk model
        # It needs GalSim version master, as of April 2017 (probably 1.5).

        # Get a Sersic bulge:
        tru_bulge_sersicn = neighbors_config['EBulgeDisk']['tru_bulge_sersicn']
        tru_bulge_rad = neighbors_config['EBulgeDisk']['tru_bulge_rad']
        tru_bulge_flux = neighbors_config['EBulgeDisk']['tru_bulge_flux']
        tru_disk_hlr = neighbors_config['EBulgeDisk']['tru_disk_hlr']
        tru_disk_tilt = neighbors_config['EBulgeDisk']['tru_disk_tilt']
        tru_disk_flux = neighbors_config['EBulgeDisk']['tru_disk_flux']
        tru_theta = neighbors_config['EBulgeDisk']['tru_theta']

        bulge = galsim.Sersic(n=tru_bulge_sersicn,
                              half_light_radius=tru_bulge_rad,
                              flux=tru_bulge_flux)
        # Make it elliptical:
        #bulge_ell = galsim.Shear(g=row["tru_bulge_g"], beta=row["tru_theta"] * galsim.degrees)
        #bulge = bulge.shear(bulge_ell)
        bulge = bulge.shear(g1=tru_g1, g2=tru_g2)

        # Get a disk
        scale_radius = tru_disk_hlr / galsim.Exponential._hlr_factor
        disk = galsim.InclinedExponential(
            inclination=tru_disk_tilt * galsim.degrees,
            scale_radius=scale_radius,
            flux=tru_disk_flux,
            scale_h_over_r=tru_disk_scale_h_over_r)
        # Rotate it in the same orientation as the bulge:
        disk = disk.rotate(tru_theta * galsim.degrees)

        # And we add those profiles, as done in GalSim demo3.py :
        gal = bulge + disk

    elif profile_type == 'Gaussian_PSF':  #you meant to draw stars all of them identical
        gal = galsim.Gaussian(flux=neighbors_config['Gaussian_PSF']['flux'],
                              sigma=neighbors_config['Gaussian_PSF']['flux'])
        #gal = gal.shear(g1=tru_g1, g2=tru_g2)

    elif profile_type == 'Stamp_PSF':
        raise RuntimeError(
            "Neighbors with Stamp_PSF, but PSF stamp is not defined in catalog"
        )
        gal = psf
        #gal = gal.shear(g1=tru_g1, g2=tru_g2)
    else:
        raise RuntimeError("Unknown galaxy profile!")

    return gal
Exemplo n.º 11
0
def drawimg(catalog,
            simgalimgfilepath="test.fits",
            simtrugalimgfilepath=None,
            simpsfimgfilepath=None,
            gsparams=None,
            sersiccut=None):
    """
	Turns a catalog as obtained from drawcat into FITS images.
	Only the position jitter and the pixel noise are randomized. All the other info is taken from the input catalog.
	So simply call me several times for the same input to get different realizations of the same galaxies.
	To specify the PSFs, add a meta["psf"] ImageInfo object to the catalog.
		
	:param catalog: an input catalog of galaxy shape parameters, as returned by drawcat.
		The corresponding stampsize must be provided as catalog.meta["stampsize"].
		If you specify a psf image in catalog.meta["psf"], your catalog must of course also contain
		PSF coordinates for that image.
		If no PSF stamps are specifed, the code will look for Gaussian PSF parameters in the catalog.
		If such parameters are not given, no PSF convolution is done.
		
	:param simgalimgfilepath: where I write my output image of simulated and noisy galaxies
	:param simtrugalimgfilepath: (optional) where I write the image without convolution and noise
	:param simpsfimgfilepath: (optional) where I write the PSFs
	
	:param sersiccut: cuts the sersic profile at this number of rad
	
	.. note::
		See this function in MomentsML v4 (great3) for attempts to speed up galsim by playing with fft params, accuracy, etc...
	
	.. note::
		About speed, if you specify trunc, better express the scale radius.
		But scale radius is crazy dependent on n, so I keep half-light-radius
		http://galsim-developers.github.io/GalSim/classgalsim_1_1base_1_1_sersic.html
		
		
	.. note::
		To use the hacks, give "metadict":{"hack":"nicobackgals"} as drawcatkwargs to sim.run.multi()...
	
	"""
    starttime = datetime.now()

    hack = catalog.meta.get("hack", None)

    if hack is None:  # The default behavior, without specific gsparams or tricks.

        if gsparams is None:
            gsparams = galsim.GSParams(maximum_fft_size=10240)

        if "nx" not in catalog.meta.keys() or "ny" not in catalog.meta.keys():
            raise RuntimeError(
                "Provide nx and ny in the meta data of the input catalog to drawimg."
            )
        if "stampsize" not in catalog.meta.keys():
            raise RuntimeError(
                "Provide stampsize in the meta data of the input catalog to drawimg."
            )

        nx = catalog.meta["nx"]
        ny = catalog.meta["ny"]
        stampsize = catalog.meta["stampsize"]  # The stamps I'm going to draw

        logger.info("Drawing images of %i galaxies on a %i x %i grid..." %
                    (len(catalog), nx, ny))
        logger.info("The stampsize for the simulated galaxies is %i." %
                    (stampsize))

        # A special function checks the combination of settings in the provided catalog:
        todo = checkcat(catalog)

        if "loadpsfimg" in todo:
            psfimg = catalog.meta["psf"].load(
            )  # Loading the actual GalSim Image
            psfinfo = catalog.meta["psf"]

        if "tru_pixel" in todo:
            # This is only if you want "effective pixels" larger than the actual pixels (related to SBE, normally you don't want this).
            pix = galsim.Pixel(
                catalog["tru_pixel"]
                [0])  # We have checked in checkcat that all values are equal.

        # Galsim random number generators
        rng = galsim.BaseDeviate()
        ud = galsim.UniformDeviate()  # This gives a random float in [0, 1)

        # We prepare the big images :
        gal_image = galsim.ImageF(stampsize * nx, stampsize * ny)
        trugal_image = galsim.ImageF(stampsize * nx, stampsize * ny)
        psf_image = galsim.ImageF(stampsize * nx, stampsize * ny)

        gal_image.scale = 1.0  # we use pixels as units. Note that if you change something here, you also have to change the jitter.
        trugal_image.scale = 1.0
        psf_image.scale = 1.0

        # And loop through the catalog:
        for row in catalog:

            # Some simplistic progress indication:
            fracdone = float(row.index) / len(catalog)
            if row.index % 500 == 0:
                logger.info("%6.2f%% done (%i/%i) " %
                            (fracdone * 100.0, row.index, len(catalog)))

            # We will draw this galaxy in a postage stamp, but first we need the bounds of this stamp.
            ix = int(row["ix"])
            iy = int(row["iy"])
            assert ix < nx and iy < ny
            bounds = galsim.BoundsI(
                ix * stampsize + 1, (ix + 1) * stampsize, iy * stampsize + 1,
                (iy + 1) *
                stampsize)  # Default Galsim convention, index starts at 1.
            gal_stamp = gal_image[bounds]
            trugal_stamp = trugal_image[bounds]
            psf_stamp = psf_image[bounds]

            # We draw the desired profile
            profile_type = params.profile_types[row["tru_type"]]

            if profile_type == "Sersic":
                if sersiccut is None:
                    trunc = 0
                else:
                    trunc = float(row["tru_rad"]) * sersiccut
                gal = galsim.Sersic(n=float(row["tru_sersicn"]),
                                    half_light_radius=float(row["tru_rad"]),
                                    flux=float(row["tru_flux"]),
                                    gsparams=gsparams,
                                    trunc=trunc)
                # We make this profile elliptical
                gal = gal.shear(g1=row["tru_g1"], g2=row["tru_g2"]
                                )  # This adds the ellipticity to the galaxy

            elif profile_type == "Gaussian":

                gal = galsim.Gaussian(flux=float(row["tru_flux"]),
                                      sigma=float(row["tru_sigma"]),
                                      gsparams=gsparams)
                # We make this profile elliptical
                gal = gal.shear(g1=row["tru_g1"], g2=row["tru_g2"]
                                )  # This adds the ellipticity to the galaxy

            elif profile_type == "EBulgeDisk":

                # A more advanced Bulge + Disk model
                # It needs GalSim version master, as of April 2017 (probably 1.5).

                # Get a Sersic bulge:
                bulge = galsim.Sersic(n=row["tru_bulge_sersicn"],
                                      half_light_radius=row["tru_bulge_hlr"],
                                      flux=row["tru_bulge_flux"])
                # Make it elliptical:
                bulge_ell = galsim.Shear(g=row["tru_bulge_g"],
                                         beta=row["tru_theta"] *
                                         galsim.degrees)
                bulge = bulge.shear(bulge_ell)

                # Get a disk
                scale_radius = row[
                    "tru_disk_hlr"] / galsim.Exponential._hlr_factor
                disk = galsim.InclinedExponential(
                    inclination=row["tru_disk_tilt"] * galsim.degrees,
                    scale_radius=scale_radius,
                    flux=row["tru_disk_flux"],
                    scale_h_over_r=row["tru_disk_scale_h_over_r"])
                # Rotate it in the same orientation as the bulge:
                disk = disk.rotate(row["tru_theta"] * galsim.degrees)

                # And we add those profiles, as done in GalSim demo3.py :
                gal = bulge + disk

            else:
                raise RuntimeError("Unknown galaxy profile!")

            # And now we add lensing, if s1, s2 and mu are different from no lensing...
            if row["tru_s1"] != 0 or row["tru_s2"] != 0 or row["tru_mu"] != 1:
                gal = gal.lens(float(row["tru_s1"]), float(row["tru_s2"]),
                               float(row["tru_mu"]))
            else:
                pass
                #logger.info("No lensing!")

            # We apply some jitter to the position of this galaxy
            xjitter = ud(
            ) - 0.5  # This is the minimum amount -- should we do more, as real galaxies are not that well centered in their stamps ?
            yjitter = ud() - 0.5
            gal = gal.shift(xjitter, yjitter)

            # We draw the pure unconvolved galaxy
            if simtrugalimgfilepath != None:
                gal.drawImage(
                    trugal_stamp,
                    method="auto")  # Will convolve by the sampling pixel.

            # We prepare/get the PSF and do the convolution:

            # Should the final operation skip the convolution by the pixel (because the PSF already is in large pixels) ?
            skip_pixel_conv = False

            if "usegausspsf" in todo:

                if row["tru_psf_sigma"] < 0.0:
                    raise RuntimeError("Unknown hack!")
                else:
                    psf = galsim.Gaussian(flux=1., sigma=row["tru_psf_sigma"])
                    psf = psf.shear(g1=row["tru_psf_g1"], g2=row["tru_psf_g2"])

                    # Let's apply some jitter to the position of the PSF (not sure if this is required, but should not harm ?)
                    psf_xjitter = ud() - 0.5
                    psf_yjitter = ud() - 0.5
                    psf = psf.shift(psf_xjitter, psf_yjitter)

                if simpsfimgfilepath != None:
                    psf.drawImage(
                        psf_stamp,
                        method="auto")  # Will convolve by the sampling pixel.

                if "tru_pixel" in todo:  # Not sure if this should only apply to gaussian PSFs, but so far this seems OK.
                    # Remember that this is an "additional" pixel convolution, not the usual sampling-related convolution that happens in drawImage.
                    galconv = galsim.Convolve([gal, psf, pix])

                else:
                    galconv = galsim.Convolve([gal, psf])

            elif "loadpsfimg" in todo:

                (inputpsfstamp,
                 flag) = tools.image.getstamp(row[psfinfo.xname],
                                              row[psfinfo.yname], psfimg,
                                              psfinfo.stampsize)
                psfpixelscale = getattr(
                    psfinfo, "pixelscale", 1.0
                )  # Using getattr so that it works with old objects as well
                if psfpixelscale > 0.5:
                    #logger.warning("You seem to be using a sampled PSF with large pixels (e.g., observed stars). I'll do my best and skip the pixel conv, but this might well lead to errors.")
                    skip_pixel_conv = True
                if flag != 0:
                    raise RuntimeError("Could not extract a %ix%i stamp at (%.2f, %.2f) from the psfimg %s" %\
                     (psfinfo.stampsize, psfinfo.stampsize, row[psfinfo.xname], row[psfinfo.yname], psfinfo.name))
                psf = galsim.InterpolatedImage(inputpsfstamp,
                                               flux=1.0,
                                               scale=psfpixelscale)
                if simpsfimgfilepath != None:
                    psf.drawImage(
                        psf_stamp, method="no_pixel"
                    )  # psf_stamp has a different size than inputpsfstamp, so this could lead to problems one day.

                #galconv = galsim.Convolve([gal,psf], real_space=False)
                galconv = galsim.Convolve([gal, psf])

            elif "nopsf" in todo:
                # Nothing to do
                galconv = gal

            else:
                raise RuntimeError("Bug in todo.")

            # Draw the convolved galaxy
            if skip_pixel_conv == False:
                galconv.drawImage(
                    gal_stamp, method="auto"
                )  # This will convolve by the image sampling pixel. Don't do this yourself ahead!
            else:
                #logger.warning("NOT computing any pixel convolution")
                galconv.drawImage(
                    gal_stamp, method="no_pixel"
                )  # Simply uses pixel-center values. Know what you are doing, see doc of galsim.

            # And add noise to the convolved galaxy:
            gal_stamp.addNoise(
                galsim.CCDNoise(rng,
                                sky_level=float(row["tru_sky_level"]),
                                gain=float(row["tru_gain"]),
                                read_noise=float(row["tru_read_noise"])))

        logger.info("Done with drawing, now writing output FITS files ...")

        gal_image.write(simgalimgfilepath)

        if simtrugalimgfilepath != None:
            trugal_image.write(simtrugalimgfilepath)

        if simpsfimgfilepath != None:
            psf_image.write(simpsfimgfilepath)

    elif hack == "nicobackgals":
        """
		This is taken and/or adapted from Nico's simulation code, to be sure to do the same thing.
			- Nico uses GalSim in units of arcsec (instaed of pixels), and we suspect that this affects the convolution.
			- Nico has different gsparams
			- Nico truncates Sersic profiles
			
		"""
        logger.info("Using special hack for nicobackgals")

        gsparams = galsim.GSParams(xvalue_accuracy=2.e-4,
                                   kvalue_accuracy=2.e-4,
                                   maxk_threshold=5.e-3,
                                   folding_threshold=1.e-2)
        pixel_scale = 0.1

        if "nx" not in catalog.meta.keys() or "ny" not in catalog.meta.keys():
            raise RuntimeError(
                "Provide nx and ny in the meta data of the input catalog to drawimg."
            )
        if "stampsize" not in catalog.meta.keys():
            raise RuntimeError(
                "Provide stampsize in the meta data of the input catalog to drawimg."
            )

        nx = catalog.meta["nx"]
        ny = catalog.meta["ny"]
        stampsize = catalog.meta["stampsize"]  # The stamps I'm going to draw

        logger.info("Drawing images of %i galaxies on a %i x %i grid..." %
                    (len(catalog), nx, ny))
        logger.info("The stampsize for the simulated galaxies is %i." %
                    (stampsize))

        # Galsim random number generators
        rng = galsim.BaseDeviate()
        ud = galsim.UniformDeviate()  # This gives a random float in [0, 1)

        # We prepare the big image, and set the pixel scale
        gal_image = galsim.ImageF(stampsize * nx,
                                  stampsize * ny,
                                  scale=pixel_scale)


        psf = galsim.Airy(lam=800, diam=1.2, obscuration=0.3, scale_unit=galsim.arcsec, flux=1./3) + \
         galsim.Airy(lam=700, diam=1.2, obscuration=0.3, scale_unit=galsim.arcsec, flux=1./3) + \
         galsim.Airy(lam=600, diam=1.2, obscuration=0.3, scale_unit=galsim.arcsec, flux=1./3)

        for row in catalog:

            # Some simplistic progress indication:
            fracdone = float(row.index) / len(catalog)
            if row.index % 500 == 0:
                logger.info("%6.2f%% done (%i/%i) " %
                            (fracdone * 100.0, row.index, len(catalog)))

            # We will draw this galaxy in a postage stamp, but first we need the bounds of this stamp.
            ix = int(row["ix"])
            iy = int(row["iy"])
            assert ix < nx and iy < ny
            bounds = galsim.BoundsI(
                ix * stampsize + 1, (ix + 1) * stampsize, iy * stampsize + 1,
                (iy + 1) *
                stampsize)  # Default Galsim convention, index starts at 1.
            gal_stamp = gal_image[bounds]

            # Drawing the galaxy
            half_light_radius = float(row["tru_rad"]) * pixel_scale
            gal = galsim.Sersic(n=float(row["tru_sersicn"]),
                                half_light_radius=half_light_radius,
                                flux=float(row["tru_flux"]),
                                gsparams=gsparams,
                                trunc=half_light_radius * 4.5)
            # We make this profile elliptical
            gal = gal.shear(
                g1=row["tru_g1"],
                g2=row["tru_g2"])  # This adds the ellipticity to the galaxy

            # And now we add lensing, if s1, s2 and mu are different from no lensing...
            if row["tru_s1"] != 0 or row["tru_s2"] != 0 or row["tru_mu"] != 1:
                gal = gal.lens(float(row["tru_s1"]), float(row["tru_s2"]),
                               float(row["tru_mu"]))
            else:
                pass
                #logger.info("No lensing!")

            # We apply some jitter to the position of this galaxy # it seems this has to be given in the image scale...
            xjitter = (ud() - 0.5) * pixel_scale
            yjitter = (ud() - 0.5) * pixel_scale
            gal = gal.shift(xjitter, yjitter)

            final = galsim.Convolve([psf, gal])

            final.drawImage(gal_stamp)

            # And add noise to the convolved galaxy:
            gal_stamp.addNoise(
                galsim.CCDNoise(rng,
                                sky_level=float(row["tru_sky_level"]),
                                gain=float(row["tru_gain"]),
                                read_noise=float(row["tru_read_noise"])))

        logger.info("Done with drawing, now writing output FITS files ...")

        gal_image.write(simgalimgfilepath)

    else:
        raise RuntimeError("Unknown hack")

    endtime = datetime.now()
    logger.info("This drawing took %s" % (str(endtime - starttime)))
import numpy as np
import galsim
import ngmix
import matplotlib.pyplot as plt
import ipdb

mcal_shear = 0.01
#true_shear = -0.02
true_shear = 0.05

gal_ideal = galsim.InclinedExponential(80 * galsim.degrees,
                                       half_light_radius=1.).rotate(
                                           20 * galsim.degrees)
psf = galsim.Gaussian(fwhm=.5)
psf_metacal = galsim.Gaussian(fwhm=0.5 * (1 + 2 * mcal_shear))
gal_ideal_observed = galsim.Convolve([gal_ideal, psf])
gal_ideal_image = gal_ideal_observed.drawImage(scale=0.206)
psf_image = psf.drawImage(scale=0.206)
psf_weight_image = np.ones_like(psf_image.array) * 1e9
weight_image = np.ones_like(gal_ideal_image.array) * 1e9

# Set up for metacalibration.
jj_im = ngmix.jacobian.DiagonalJacobian(scale=0.206,
                                        x=gal_ideal_image.center.x,
                                        y=gal_ideal_image.center.y)
jj_psf = ngmix.jacobian.DiagonalJacobian(scale=0.206,
                                         x=psf_image.center.x,
                                         y=psf_image.center.y)
psf_obs = ngmix.Observation(psf_image.array,
                            weight=psf_weight_image,
                            jacobian=jj_psf)
Exemplo n.º 13
0
 def _setup_gal(self, pars):
     self.gal = galsim.InclinedExponential(**pars.galsim_kw)
     self.gal = self.gal.rotate(pars.PA.to('degree').value * galsim.degrees)
Exemplo n.º 14
0
def test_eq_ne():
    """ Check that equality/inequality works as expected."""
    gsp = galsim.GSParams(folding_threshold=1.1e-3)

    # First test that some different initializations that should be equivalent:
    gals = [galsim.InclinedExponential(0.1*galsim.radians, 3.0),
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, 0.3),  # default h/r = 0.1
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, scale_height=0.3),
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, scale_h_over_r=0.1),
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, flux=1.0),  # default flux=1
            galsim.InclinedExponential(-0.1*galsim.radians, 3.0),  # negative i is equivalent
            galsim.InclinedExponential((np.pi--0.1)*galsim.radians, 3.0),  # also pi-theta
            galsim.InclinedExponential(18./np.pi*galsim.degrees, 3.0),
            galsim.InclinedExponential(inclination=0.1*galsim.radians, scale_radius=3.0,
                                       scale_height=0.3, flux=1.0),
            galsim.InclinedExponential(flux=1.0, scale_radius=3.0,
                                       scale_height=0.3, inclination=0.1*galsim.radians)]

    for gal in gals[1:]:
        print(gal)
        gsobject_compare(gal, gals[0])

    gals = [galsim.InclinedExponential(0.1*galsim.radians, 3.0, 0.3),
            galsim.InclinedExponential(0.1*galsim.degrees, 3.0, 0.3),
            galsim.InclinedExponential(0.1*galsim.degrees, 3.0, scale_h_over_r=0.2),
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, 3.0),
            galsim.InclinedExponential(0.2*galsim.radians, 3.0, 0.3),
            galsim.InclinedExponential(0.1*galsim.radians, 3.1, 0.3),
            galsim.InclinedExponential(0.1*galsim.radians, 3.1),
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, 0.3, flux=0.5),
            galsim.InclinedExponential(0.1*galsim.radians, 3.0, 0.3, gsparams=gsp)]
    all_obj_diff(gals)