Tutorials
The GalSim/examples
directory contains demo files serve as 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 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 galsim Executable.
Both versions of each demo produce identical output files. Internally, this serves as a useful 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.
Demo 1
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 add a constant level of Gaussian noise to the image.
New features in the Python file:
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()
New features in the YAML file:
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
Demo 2
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. The noise is drawn from a Poisson distribution using the flux from both the object and a background sky level to determine the variance in each pixel.
New features in the Python file:
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)
New features in the YAML file:
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
Demo 3
This demo gets reasonably close to including all the principal features of an image from a ground-based telescope. The galaxy is represented as the sum of a bulge and a disk, where each component is represented by 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.
New features in the Python file:
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)
New features in the YAML file:
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
Demo 4
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.
New features in the Python file:
cat = galsim.Catalog(file_name, dir)
obj = galsim.Moffat(beta, fwhm, trunc)
obj = galsim.DeVaucouleurs(flux, half_light_radius)
obj = galsim.RandomKnots(npoints, half_light_radius, flux)
obj = galsim.Add([list of objects])
obj = obj.shift(dx,dy)
galsim.fits.writeMulti([list of images], file_name)
New features in the YAML file:
obj type : Moffat (…, trunc)
obj type : DeVaucouleurs (flux, half_light_radius)
obj type : RandomKnots (npoints, half_light_radius, flux)
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
Demo 5
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.
New features in the Python file:
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.
New features in the YAML file:
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
Demo 6
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 as described in Downloading the COSMOS Catalog.
The galaxy images are already convolved with the effective PSF for the original observations, so GalSim considers the galaxy profile to be the observed image deconvolved by that PSF (also distributed with the galaxy data). 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.
New features in the Python file:
real_cat = galsim.RealGalaxyCatalog(file_name, dir)
obj = galsim.Gaussian(fwhm, flux)
obj = galsim.RealGalaxy(real_cat, index, flux)
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)
New features in the YAML file:
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
Demo 7
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 into the same larger image 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.
New features in the Python file:
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(…)
New features in the YAML file:
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.
Demo 8
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 given 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.)
New features in the Python file:
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)
New features in the YAML file:
stamp : retry_failures
shear type : Eta1Eta2 (eta1, eta2)
image : nproc
Demo 9
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 located at random positions in 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.
New features in the Python file:
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.true_center
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)
bounds.isDefined()
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.
New features in the YAML file:
obj type : OpticalPSF (lam, diam, …, trefoil1, trefoil2, nstruts, strut_thick, strut_angle)
obj type : InclinedExponential (scale_radius, scale_h_over_r, inclination)
angle type : Radians
shear type : NFWHaloShear (redshift)
float type : NFWHaloMagnification (redshift)
float type : RandomDistribution(function, x_min, x_max)
input : nfw_halo (mass, conc, redshift)
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
Demo 10
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).
New features in the Python file:
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)
New features in the YAML file:
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
Demo 11
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 shear 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 parametric fits to the same observed galaxies. The flux and size distribution are thus realistic for an I < 23.5 magnitude limited sample.
New features in the Python file:
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(gal_type, rng, noise_pad_size)
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
New features in the YAML file:
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).
Using $ as a shorthand for Eval type.
Demo 12
This demo introduces wavelength-dependent profiles. Three kinds of chromatic profiles are demonstrated:
A chromatic object representing a DeVaucouleurs galaxy with an early-type SED at redshift 0.8. This galaxy is drawn using the six LSST filters, which demonstrate that the galaxy is a g-band dropout.
A two-component bulge+disk galaxy, in which the bulge and disk have different SEDs.
A wavelength-dependent atmospheric PSF, which includes the effect of differential chromatic refraction and the wavelength dependence of Kolmogorov-turbulence-induced seeing. This PSF is convolved with a simple Exponential galaxy.
New features in the Python file:
SED = galsim.SED(wave, flambda, wave_type, flux_type)
SED2 = SED.atRedshift(redshift)
bandpass = galsim.Bandpass(filename, wave_type)
bandpass2 = bandpass.truncate(relative_throughput)
bandpass3 = bandpass2.thin(rel_err)
gal = GSObject * SED
obj = galsim.Add([list of ChromaticObjects])
ChromaticObject.drawImage(bandpass)
PSF = galsim.ChromaticAtmosphere(GSObject, base_wavelength, zenith_angle)
New features in the YAML file:
- sedfile_name, wave_type, flux_type, norm_flux_density, norm_wavelength,
norm_flux, norm_bandpass
bandpass : filename, wave_type, thin
gal : redshift
psf_type : ChromaticAtmosphere (base_profile, base_wavelength, latitude, HA)
Demo 13
This script is intended to produce a relatively realistic scene of galaxies and stars as will be observed by the Roman Space Telescope, including the Roman PSF, WCS, and various NIR detector effects.
It introduces several non-idealities arising from NIR detectors, in particular those that will be observed and accounted for in the Roman Space Telescope. 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.
It also uses chromatic photon shooting, which is generally a more efficient way to simulate scenes with many faint galaxies. The default FFT method for drawing chromatically is fairly slow, since it needs to integrate the image over the bandpass. With photon shooting, the photons are assigned wavelengths according to the SED of the galaxy, and then each photon has the appropriate application of the chromatic PSF according to the wavelength.
New features in the Python file:
image.quantize()
obj = galsim.DeltaFunction(flux)
galsim.roman.addReciprocityFailure(image)
galsim.roman.applyNonlinearity(image)
galsim.roman.applyIPC(image)
galsim.roman.getBandpasses()
galsim.roman.getPSF()
galsim.roman.getWCS()
galsim.roman.allowedPos()
galsim.roman.getSkyLevel()
New features in the YAML file:
Top-level field modules
obj type: RomanPSF
image type: RomanSCA
draw_method=phot in conjunction with chromatic objects
Multiple random seeds (particular so one can repeat the same values for multiple images)
rng_num specification in various fields
Multiple inputs of the same type. Use num to specify which item in the list to use each time.
Advanced Simulations
Great3 Simulations
In the directory GalSim/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).
Significant features in these files:
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
)custom extra output type (e.g. noise_free in
cgc.yaml
)top-level module field
use of ‘$’ and ‘@’ shorthand in Eval items.
DES Simulations
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.
Significant features in these files:
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
)