Source code for xlens.simulator.layout.shifts

"""Helper functions that return structured arrays of (dx, dy) shifts
in arcseconds."""

import numpy as np


[docs] def get_grid_shifts(*, rng, dim, pixel_scale, spacing): """ get a set of gridded shifts, with random shifts at the pixel scale Parameters ---------- rng: numpy.random.RandomState The random number generator dim: int Dimensions of the final image pixel_scale: float pixel scale spacing: float Spacing of the lattice Returns ------- shifts: array Array with x, y in the image plane """ width = dim * pixel_scale n_on_side = int(dim / spacing * pixel_scale) ntot = n_on_side**2 # ix/iy are really on the sky grid = spacing*(np.arange(n_on_side) - (n_on_side-1)/2) shifts = np.zeros(ntot, dtype=[("dx", "f8"), ("dy", "f8")]) i = 0 for ix in range(n_on_side): for iy in range(n_on_side): dx = grid[ix] + pixel_scale * rng.uniform(low=-0.5, high=0.5) dy = grid[iy] + pixel_scale * rng.uniform(low=-0.5, high=0.5) shifts["dx"][i] = dx shifts["dy"][i] = dy i += 1 pos_bounds = (-width/2, width/2) msk = ( (shifts["dx"] >= pos_bounds[0]) & (shifts["dx"] <= pos_bounds[1]) & (shifts["dy"] >= pos_bounds[0]) & (shifts["dy"] <= pos_bounds[1]) ) shifts = shifts[msk] return shifts
[docs] def get_hex_shifts(*, rng, dim, pixel_scale, spacing): """ get a set of hex grid shifts, with random shifts at the pixel scale Parameters ---------- rng: numpy.random.RandomState The random number generator dim: int Dimensions of the final image pixel_scale: float pixel scale spacing: float Spacing of the hexagonal lattice Returns ------- shifts: array Array with dx, dy offset fields for each point, in arcsec """ from hexalattice.hexalattice import create_hex_grid width = dim * pixel_scale n_on_side = int(width / spacing) + 1 nx = int(n_on_side * np.sqrt(2)) # the factor of 0.866 makes sure the grid is square-ish ny = int(n_on_side * np.sqrt(2) / 0.8660254) # here the spacing between grid centers is 1 hg, _ = create_hex_grid(nx=nx, ny=ny, rotate_deg=rng.uniform() * 360) # convert the spacing to right number of pixels # we also recenter the grid since it comes out centered at 0,0 hg *= spacing upos = hg[:, 0].ravel() vpos = hg[:, 1].ravel() # dither upos += pixel_scale * rng.uniform(low=-0.5, high=0.5, size=upos.shape[0]) vpos += pixel_scale * rng.uniform(low=-0.5, high=0.5, size=vpos.shape[0]) pos_bounds = (-width/2, width/2) msk = ( (upos >= pos_bounds[0]) & (upos <= pos_bounds[1]) & (vpos >= pos_bounds[0]) & (vpos <= pos_bounds[1]) ) upos = upos[msk] vpos = vpos[msk] ntot = upos.shape[0] shifts = np.zeros(ntot, dtype=[("dx", "f8"), ("dy", "f8")]) shifts["dx"] = upos shifts["dy"] = vpos return shifts
[docs] def get_random_shifts(*, rng, dim, pixel_scale, size): """ get a set of random shifts in a square, with random shifts at the pixel scale Parameters ---------- rng: numpy.random.RandomState The random number generator dim: int Dimensions of the final image pixel_scale: float pixel scale size: int Number of objects to draw. Returns ------- shifts: array Array with dx, dy offset fields for each point, in arcsec """ halfwidth = dim / 2.0 if halfwidth < 0: raise ValueError("dim < 0") low = -halfwidth * pixel_scale high = halfwidth * pixel_scale shifts = np.zeros(size, dtype=[("dx", "f8"), ("dy", "f8")]) shifts["dx"] = rng.uniform(low=low, high=high, size=size) shifts["dy"] = rng.uniform(low=low, high=high, size=size) return shifts
[docs] def get_random_disk_shifts(*, rng, dim, pixel_scale, size): """Gets a set of random shifts on a disk, with random shifts at the pixel scale Parameters ---------- rng: numpy.random.RandomState The random number generator dim: int Dimensions of the final image pixel_scale: float pixel scale size: int Number of objects to draw. Returns ------- shifts: array Array with dx, dy offset fields for each point, in arcsec """ radius = dim / 2.0 * pixel_scale if radius < 0: raise ValueError("radius < 0") radius_square = radius**2. # evenly distributed within a radius, min(nx, ny)*rfrac rarray = np.sqrt(radius_square*rng.rand(size)) # radius tarray = rng.uniform(0., 2*np.pi, size) # theta (0, pi/nrot) shifts = np.zeros(size, dtype=[("dx", "f8"), ("dy", "f8")]) shifts["dx"] = rarray*np.cos(tarray) shifts["dy"] = rarray*np.sin(tarray) return shifts