-
Notifications
You must be signed in to change notification settings - Fork 107
Tutorials
The examples
directory contains demo files that essentially amount to tutorials on how to use the
GalSim code.
There are versions of each demo in both Python (demo*.py
) and YAML (demo*.yaml
).
The demos start fairly simple and progress to more sophisticated simulations, adding
a modest number of new features each time with copious documentation about the new features
being introduced.
The YAML files are run using the galsim
executable, which parses the YAML file into a Python
dict and runs this through the config parsing module in GalSim. For complicated simulations,
we generally recommend using config files such as these, since they tend to be more quickly
readable than the Python scripts, which makes it easy to see how to modify them to effect
some desired change in the simulation. For more information about running the galsim
executable, see the main Config Documentation page.
Both versions of each demo produce identical output files. Internally, this serves as a useful unit test of the config parsing code. But it also serves as a kind of implicit documentation about how some of the config features are handled by GalSim.
This first demo is about as simple as it gets. We draw an image of a single galaxy convolved with a PSF and write it to disk. We use a circular Gaussian profile for both the PSF and the galaxy. And we add a constant level of Gaussian noise to the image.
- obj = galsim.Gaussian(flux, sigma)
- obj = galsim.Convolve([list of objects])
- image = obj.drawImage(scale)
- image.added_flux (Only present after a drawImage command.)
- noise = galsim.GaussianNoise(sigma)
- image.addNoise(noise)
- image.write(file_name)
- image.FindAdaptiveMom()
- top level fields gal, psf, image, output
- obj type : Gaussian (flux, sigma)
- image : pixel_scale
- image : noise
- noise type : Gaussian (sigma)
- output : dir, file_name
This demo is a bit more sophisticated, but still pretty basic. We still only make a single image, but now the galaxy has an exponential radial profile and is sheared. The PSF is a circular Moffat profile. And the noise is Poisson using the flux from both the object and a background sky level to determine the variance in each pixel.
- obj = galsim.Exponential(flux, scale_radius)
- obj = galsim.Moffat(beta, flux, half_light_radius)
- obj = obj.shear(g1, g2) -- with explanation of other ways to specify shear
- rng = galsim.BaseDeviate(seed)
- noise = galsim.PoissonNoise(rng, sky_level)
- galsim.hsm.EstimateShear(image, image_epsf)
- obj type : Exponential (flux, scale_radius)
- obj type : Moffat (flux, beta, half_light_radius)
- obj : shear
- shear type : G1G2 (g1, g2)
- noise type : Poisson (sky_level)
- image : random_seed
This demo is getting reasonably close to including all the principal features of an image from a ground-based telescope. The galaxy is a bulge plus disk, where each component is a sheared Sersic profile (with different Sersic indices). The PSF has both atmospheric and optical components. The atmospheric component is a Kolmogorov turbulent spectrum. The optical component includes defocus, coma and astigmatism, as well as obscuration from a secondary mirror. The noise model includes both a gain and read noise. And finally, we include the effect of a slight telescope distortion.
- obj = galsim.Sersic(n, flux, half_light_radius)
- obj = galsim.Sersic(n, flux, scale_radius)
- obj = galsim.Kolmogorov(fwhm)
- obj = galsim.OpticalPSF(lam_over_diam, defocus, coma1, coma2, astig1, astig2, obscuration)
- obj = obj.shear(e, beta) -- including how to specify an angle in GalSim
- shear = galsim.Shear(q, beta)
- obj = obj.shear(shear)
- obj3 = x1 * obj1 + x2 * obj2
- obj = obj.withFlux(flux)
- image = galsim.ImageF(image_size, image_size)
- image = obj.drawImage(image, wcs)
- image = obj.drawImage(method='sb')
- world_profile = wcs.toWorld(profile)
- shear3 = shear1 + shear2
- noise = galsim.CCDNoise(rng, sky_level, gain, read_noise)
- obj type : Sum (items)
- obj type : Convolve (items)
- obj type : Sersic (flux, n, half_light_radius)
- obj type : Sersic (flux, n, scale_radius)
- obj type : Kolmogorov (fwhm)
- obj type : OpticalPSF (lam_over_diam, defocus, coma1, coma2, astig1, astig2, obscuration)
- obj : ellip
- shear type : QBeta (q, beta) -- including how to specify an angle
- shear type : EBeta (e, beta)
- noise type : CCD (sky_level, gain, read_noise)
- image : size
- image : wcs
- wcs type : Shear
- output : psf
This demo is our first one to create multiple images. Typically, you would want each object
to have at least some of its attributes vary when you are drawing multiple images (although
not necessarily -- you might just want different noise realization of the same profile).
The easiest way to do this is to read in the properties from a catalog, which is what we
do in this case. The PSF is a truncated Moffat profile, and the galaxy is bulge plus disk.
Both components get many of their parameters from an input catalog. We also shift the
profile by a fraction of a pixel in each direction so the effect of pixelization varies
among the images. Each galaxy has the same applied shear. The noise is simple Poisson noise.
We write the images out into a multi-extension fits file.
- cat = galsim.Catalog(file_name, dir)
- obj = galsim.Moffat(beta, fwhm, trunc)
- obj = galsim.DeVaucouleurs(flux, half_light_radius)
- obj = galsim.Add([list of objects])
- obj = obj.shift(dx,dy)
- galsim.fits.writeMulti([list of images], file_name)
- obj type : Moffat (..., trunc)
- obj type : DeVaucouleurs (flux, half_light_radius)
- value type : Catalog (col)
- obj : shift
- shift type : XY (x, y)
- shear type : E1E2 (e1, e2)
- image : xsize, ysize
- top level field input
- input : catalog (file_name, dir)
- output type : MultiFits (file_name, dir)
- Using both ellip and shear for the same object
- Using variables in a YAML file
This demo is intended to mimic a Great08 (Bridle, et al, 2010) LowNoise image.
We produce a single image made up of tiles of postage stamps for each individual object.
(We only do 10 x 10 postage stamps rather than 100 x 100 as they did in the interest of time.)
Each postage stamp is 40 x 40 pixels. One image is all stars. A second image is all galaxies.
The stars are truncated Moffat profiles. The galaxies are Exponential profiles.
(Great08 mixed pure bulge and pure disk for its LowNoise run. We just use disks to
make things simpler. However see demo3 for an example of using bulge+disk galaxies.)
The galaxies are oriented randomly, but in 90 degree-rotated pairs to cancel the effect of
shape noise. The applied shear is the same for each galaxy.
- ud = galsim.UniformDeviate(seed)
- gd = galsim.GaussianDeviate(ud, sigma)
- ccdnoise = galsim.CCDNoise(ud)
- image *= scalar
- bounds = galsim.BoundsI(xmin, xmax, ymin, ymax)
- pos = bounds.center()
- pos.x, pos.y
- sub_image = image[bounds]
- Build a single large image, and access sub-images within it.
- Set the galaxy size based on the PSF size and a resolution factor.
- Set the object flux according to a target S/N value.
- Use 90 degree-rotated pairs for the intrinsic galaxy shapes.
- Shift by a random (dx, dy) drawn from a unit circle top hat.
- gal : resolution
- gal : signal_to_noise
- stamp type : Ring (first, num)
- value type : RandomGaussian (sigma, min, max)
- angle type : Random
- shift type : RandomCircle (radius)
- image type : Tiled (nx_tiles, ny_tiles, stamp_xsize, stamp_ysize, border)
- output type : Fits (file_name, dir)
- output.psf : shift
This demo uses real galaxy images from COSMOS observations. The catalog of real galaxy images distributed with GalSim only includes 100 galaxies, but you can download a much larger set of images here.
The galaxy images include images of the effective PSF for the original observations, so GalSim considers the galaxy profile to be the observed image deconvolved by that PSF. In this case, we then randomly rotate the galaxies, apply a given gravitational shear as well as gravitational magnification, and then finally convolve by a double Gaussian PSF. The final image can of course have any pixel scale, not just that of the original images. The output for this demo is to a FITS "data cube". With DS9, this can be viewed with a slider to quickly move through the different images.
- real_cat = galsim.RealGalaxyCatalog(file_name, dir)
- obj = galsim.Gaussian(fwhm, flux)
- obj = galsim.RealGalaxy(real_cat, index)
- obj = obj.rotate(theta)
- obj = obj.magnify(mu)
- image += background
- noise = galsim.PoissonNoise() # with no sky_level given
- obj.drawImage(..., offset)
- galsim.fits.writeCube([list of images], file_name)
- input : real_catalog (file_name, dir, image_dir)
- obj type : RealGalaxy (index)
- obj : rotate
- obj : magnify
- image : sky_level
- image : offset
- value type : Sequence (first, last, step)
- output type : DataCube (file_name, dir, nimages)
- Using YAML multiple document feature to do more than one thing
This demo introduces drawing profiles with photon shooting rather than doing the convolution with an FFT. It makes images using 5 different kinds of PSF and 5 different kinds of galaxy. Some of the parameters (flux, size and shape) are random variables, so each of the 25 pairings is drawn 4 times with different realizations of the random numbers. The profiles are drawn twice: once with the FFT method, and once with photon shooting. The two images are drawn side by side so it is easy to visually compare the results. The 100 total profiles are written to a FITS data cube, which makes it easy to scroll through the images comparing the two drawing methods.
- obj = galsim.Airy(lam_over_diam)
- obj = galsim.Sersic(n, half_light_radius, trunc)
- psf = galsim.OpticalPSF(..., aberrations=aberrations, ...)
- obj = obj.dilate(scale)
- str(obj)
- image.scale = pixel_scale
- obj.drawImage(image, method='fft')
- obj.drawImage(image, method='phot', max_extra_noise, rng)
- dev = galsim.PoissonDeviate(rng, mean)
- noise = galsim.DeviateNoise(dev)
- writeCube(..., compress='gzip')
- gsparams = galsim.GSParams(...)
- obj type : List (items)
- obj type : Airy (lam_over_diam)
- obj type : Sersic (..., trunc)
- obj : dilate
- value type : Sequence (..., repeat, index_key)
- value type : Random (min, max)
- image type : Tiled (..., stamp_size, xborder, yborder)
- stamp : draw_method (fft or phot)
- stamp : gsparams
- output : file_name with .gz, .bz2 or .fz extension automatically uses compression.
In this demo, we show how to run the GalSim config processing using a python dict rather than using a config file. The previous demos have shown what Python code corresponds to the give YAML files. Now we turn the tables and show how to use some of the machinery in the GalSim configuration processing from within Python itself.
This could be useful if you want to use the config machinery to build the images, but then rather than write the images to disk, you want to keep them in memory and do further processing with them. (e.g. Run your shape measurement code on the images from within python.)
- galsim.config.Process(config, logger)
- galsim.config.ProcessInput(config, logger)
- galsim.config.BuildFile(config, file_num, logger)
- image = galsim.config.BuildImage(config, image_num, logger)
- galsim.fits.read(file_name)
- stamp : retry_failures
- image : nproc
This script simulates cluster lensing or galaxy-galaxy lensing. The gravitational shear applied to each galaxy is calculated for an NFW halo mass profile. We simulate observations of galaxies around 20 different clusters -- 5 each of 4 different masses. Each cluster has its own file, organized into 4 directories (one for each mass). For each cluster, we draw 20 lensed galaxies at random positions of the image. The PSF is appropriate for a space-like simulation. (Some of the numbers used are the values for HST.) And we apply a cubic telescope distortion for the WCS. Finally, we also output a truth catalog for each output image that could be used for testing the accuracy of shape or flux measurements.
- psf = OpticalPSF(lam, diam, ..., trefoil1, trefoil2, nstruts, strut_thick, strut_angle)
- im = galsim.ImageS(xsize, ysize, wcs)
- pos = galsim.PositionD(x, y)
- nfw = galsim.NFWHalo(mass, conc, z, omega_m, omega_lam)
- g1,g2 = nfw.getShear(pos, z)
- mag = nfw.getMagnification(pos, z)
- distdev = galsim.DistDeviate(rng, function, x_min, x_max)
- pos = bounds.trueCenter()
- wcs = galsim.UVFunction(ufunc, vfunc, xfunc, yfunc, origin)
- wcs.toWorld(profile, image_pos)
- wcs.makeSkyImage(image, sky_level)
- image_pos = wcs.toImage(pos)
- image.invertSelf()
- truth_cat = galsim.OutputCatalog(names, types)
- Make multiple output files.
- Place galaxies at random positions on a larger image.
- Write a bad pixel mask and a weight image as the second and third HDUs in each file.
- Use multiple processes to construct each file in parallel.
- obj type : OpticalPSF (lam, diam, ..., trefoil1, trefoil2, nstruts, strut_thick, strut_angle)
- shear type : NFWHaloShear (redshift)
- float type : NFWHaloMagnification (redshift)
- float type : RandomDistribution(function, x_min, x_max)
- input : nfw_halo (mass, conc, redshift)
- shear type : Eta1Eta2 (eta1, eta2)
- shear type : Sum (items)
- image type : Scattered (size, nobjects)
- wcs type : UVFunction (ufunc, vfunc, xfunc, yfunc, origin)
- str type : NumberedFile (root, num, ext, digits)
- str type : FormattedStr (format, items)
- pos type : RandomCircle (..., inner_radius)
- value type : Sequence (..., nitems)
- output : nproc
- output : weight
- output : badpix
- output : truth
- output : skip
- output : noclobber
This script uses both a variable PSF and variable shear, taken from a power spectrum, along the lines of a Great10 (Kitching, et al, 2012) image. The galaxies are placed on a grid (10 x 10 in this case, rather than 100 x 100 in the interest of time.) Each postage stamp is 48 x 48 pixels. Instead of putting the PSF images on a separate image, we package them as the second HDU in the file. For the galaxies, we use a random selection from 5 specific RealGalaxy objects, selected to be 5 particularly irregular ones. (These are taken from the same catalog of 100 objects that demo6 used.) The galaxies are oriented in a ring test (Nakajima & Bernstein 2007) of 20 each. And we again output a truth catalog with the correct applied shear for each object (among other information).
- im.wcs = galsim.OffsetWCS(scale, origin)
- rng = galsim.BaseDeviate(seed)
- obj = galsim.RealGalaxy(real_galaxy_catalog, id)
- obj = galsim.Convolve([list], real_space)
- ps = galsim.PowerSpectrum(e_power_function, b_power_function)
- g1,g2 = ps.buildGrid(grid_spacing, ngrid, rng)
- g1,g2 = ps.getShear(pos)
- galsim.random.permute(rng, list1, list2, ...)
- Choosing PSF parameters as a function of (x,y)
- Selecting RealGalaxy by ID rather than index.
- Putting the PSF image in a second HDU in the same file as the main image.
- Using PowerSpectrum for the applied shear.
- Doing a full ring test (i.e. not just 90 degree rotated pairs)
- obj type : Ring (..., full_rotation)
- obj type : RealGalaxy (..., id)
- type : Eval using world_pos variable, user-defined variables and math functions
- type : Current
- shear_value : PowerSpectrumShear
- pos_value : RTheta (r, theta)
- image type : Tiled (..., order)
- input : power_spectrum (e_power_function, b_power_function)
- output.psf : hdu, signal_to_noise, draw_method, offset
- output.truth : hdu
- Evaluated values in output.truth.columns
This script uses a constant PSF from real data (an image read in from a bzipped FITS file, not a parametric model) and variable shear and magnification according to some cosmological model for which we have a tabulated power spectrum at specific k values only. The 288 galaxies in the 0.1 x 0.1 degree field (representing a number density of 8/arcmin^2) are randomly located and permitted to overlap. For the galaxies, we use a mix of real and parametric galaxies modeled off the COSMOS observations with the Hubble Space Telescope. The real galaxies are similar to those used in demo10. The parametric galaxies are based on parameter fits to the same observed galaxies. The flux and size distribution are thus realistic for an I < 23.5 magnitude limited sample.
- coord = galsim.CelestialCoord(ra, dec)
- wcs = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin)
- wcs = galsim.TanWCS(affine, world_origin, units)
- psf = galsim.InterpolatedImage(psf_filename, scale, flux)
- tab = galsim.LookupTable(file)
- cosmos_cat = galsim.COSMOSCatalog(file_name, dir)
- gal = cosmos_cat.makeGalaxy(index, gal_type, noise_pad_size, rng)
- ps = galsim.PowerSpectrum(..., units)
- gal = gal.lens(g1, g2, mu)
- image.whitenNoise(correlated_noise)
- image.symmetrizeNoise(correlated_noise)
- vn = galsim.VariableGaussianNoise(rng, var_image)
- image.addNoise(cn)
- image.setOrigin(x,y)
- angle.dms(), angle.hms()
- Power spectrum shears and magnifications for non-gridded positions.
- Reading a compressed FITS image (using BZip2 compression).
- Writing a compressed FITS image (using Rice compression).
- Writing WCS information to a FITS header that ds9 reads as RA, Dec
- obj type : InterpolatedImage(image, scale)
- obj type : COSMOSGalaxy
- obj : scale_flus
- image : draw_method (no_pixel)
- input : power_spectrum (e_power_file, delta2, units)
- input : cosmos_catalog (file_name, dir, use_real)
- image : index_convention
- image.noise : whiten
- image.noise : symmetrize
- wcs type : Tan(dudx, dudy, dvdx, dvdy, units, origin, ra, dec)
- top level field eval_variables
- Power spectrum shears and magnifications for non-gridded positions.
- Reading a compressed FITS image (using BZip2 compression).
- Writing a compressed FITS image (using Rice compression).
This demo introduces the chromatic objects module galsim.chromatic, which handles wavelength- dependent profiles. Three uses of this module are demonstrated:
- A chromatic object representing a De Vaucouleurs galaxy with a early-type SED at redshift 0.8 is created. The galaxy is then drawn using the six LSST filter throughput curves to demonstrate that the galaxy is a g-band dropout.
- A two-component bulge+disk galaxy, in which the bulge and disk have different SEDs, is created and then drawn using LSST filters.
- A wavelength-dependent PSF is created to represent atmospheric effects of differential chromatic refraction, and the wavelength dependence of Kolmogorov-turbulence-induced seeing. This PSF is used to draw a single Sersic galaxy in the LSST filters.
- SED = galsim.SED(wave, flambda)
- SED2 = SED.atRedshift(redshift)
- bandpass = galsim.Bandpass(filename)
- bandpass2 = bandpass.truncate(relative_throughput)
- bandpass3 = bandpass2.thin(rel_err)
- gal = galsim.Chromatic(GSObject, SED)
- gal = GSObject * SED
- obj = galsim.Add([list of ChromaticObjects])
- ChromaticObject.drawImage(bandpass)
- PSF = galsim.ChromaticAtmosphere(GSObject, base_wavelength, zenith_angle)
This demo currently does not have a YAML version. The config processing of chromatic objects has not been implemented yet.
This script introduces non-idealities arising from NIR detectors, in particular those that will be observed and accounted for in the WFIRST survey. Three such non-ideal effects are demonstrated, in the order in which they are introduced in the detectors:
- Reciprocity failure: Flux-dependent sensitivity of the detector.
- Non-linearity: Charge-dependent gain in converting from units of electrons to ADU. Non-linearity in some form is also relevant for CCDs in addition to NIR detectors.
- Interpixel capacitance: Influence of charge in a pixel on the voltage reading of neighboring ones.
The purpose of the demo is two-fold: (1) to show the effects of detector non-idealities on images from NIR detectors, and (2) to illustrate the full image generation process, including all sources of noise at appropriate stages.
- image.quantize()
- galsim.wfirst.addReciprocityFailure(image)
- galsim.wfirst.applyNonlinearity(image)
- galsim.wfirst.applyIPC(image)
- galsim.wfirst.getBandpasses()
- galsim.wfirst.getPSF()
- galsim.wfirst.getWCS()
- galsim.wfirst.allowedPos()
- galsim.wfirst.getSkyLevel()
This demo currently does not have a YAML version. The config processing of chromatic objects has not been implemented yet.
In the directory examples/great3
there are YAML config files that perform essentially the same
simulations that were done for Great3. The config apparatus had not matured sufficiently by the
time the Great3 sims were run, so these are not what the Great3 team used. However, the files
in this directory produce essentially equivalent simulations as those used in Great3.
So far there are only config files for the cgc and rgc branches of Great3, but we plan to add the files for the other branches (Issue #699).
- template option to load another config file and then modify a few aspects of it. (e.g. rgc.yaml)
- template option to load only a particular field from another config file. (e.g. cgc_psf.yaml)
- stamp.reject
- custom value type (e.g. Great3Reject in cgc.yaml)
- top-level module field
- use of '$' and '@' shorthand in Eval items.
In the directory examples/des
there are YAML config files that showcase some of the classes
defined in the galsim.des
module. These are mostly gratuitous demos designed to showcase
various features, although meds.yaml
is very close to a real simulation we actually used
in DES for testing shear measurements.
- top-level module field
- special object types from galsim.des module (e.g. DES_Shapelet and DES_PSFEx in draw_psf.yaml)
- special output type from galsim.des module (e.g. MEDS in meds.yaml)
- custom value type (e.g. HSM_Shape_Measure in meds.yaml, LogNormal in blend.yaml)
- custom WCS type (e.g. DES_Local in meds.yaml)
- custom input type (e.g. des_wcs in meds.yaml)
- custom stamp types (e.g. Blend in blend.yaml and BlendSet in blendset.yaml)
- custom extra output type (e.g. deblend in blend.yaml)