grale.grid

This module contains functions to create a subdivision grid that’s used in the lens inversion procedure. Apart from a uniformly subdivided grid, it is also possible to lay out the grid based on some kind of density map, using a finer subdivision where the integrated density is higher. This density could be the projected mass density of a gravitational lens, or even the observed light distribution in a FITS file.

Examples for how these functions can be used, can be found in the notebooks gridtests.ipynb and fittest.ipynb.

GridException

exception grale.grid.GridException

An exception that’s generated when something goes wrong with the grid creation.

MultiGridCreator

class grale.grid.MultiGridCreator(regionSize=None, regionCenter=None, multiRegionInfo=None, defaultRandomFraction=0.05)

This is a class to manage the grid creation for one or more regions. It allows you to first define the regions, and then ask for them to be subdivided uniformly (see getUniformGrid()) or using the subdivision algorithm (see getSubdivisionGrid()). It is used by the InversionWorkSpace class to manage the inversion regions.

__init__(regionSize=None, regionCenter=None, multiRegionInfo=None, defaultRandomFraction=0.05)

Initializes the MultiGridCreator object.

Arguments:

  • regionSize and regionCenter: if these are specified, multiRegionInfo must be None, and they then specify a the size and center of a single square region that will be subdivided by other functions in the class. The regionCenter parameter is optional and defaults to (0, 0)

  • multiRegionInfo: it is also possible to specify multiple square regions that should be subdivided at the same time, in a similar way (uniformly or using the subdivision algorithm). This should then be a list of dictionaries, each having a "size" key and optionally a "center" key. The regionSize and regionCenter arguments should be None if this is used.

  • defaultRandomFraction: each time getUniformGrid() or getSubdivisionGrid() is called, some random offset is added to the center(s) of the region(s). If this is a number, it specifies the fraction of the size that an offset can be. It is also possible to specify a function, which will be called with size and center of a region as its two arguments, and should return the size and center to actually use.

getSubdivisionGrid(lensOrLensInfo, minSquares, maxSquares, startSubDiv=1, randomFraction=None, lensFilter=None, lensFilterParams={}, lensInfoFilter=None, lensInfoFilterParams={}, excludeFunction=None, checkSubDivFunction=None, renderer='default', feedbackObject='default')

Based on the region information supplied by the constructor or by setRegionSize(), this subdivides the regions using the algorithm from createMultiSubdivisionGridForFunction(), which inspects the density information from lensOrLensInfo

Arguments:

  • lensOrLensInfo: should either be a single LensInfo or DensInfo instance, or a single gravitational lens model. If the latter is the case, for each region it will be converted to a LensInfo object, to get information about the density.

  • minSquares and maxSquares: construct a subdivision grid with a total number of grid cells between these bounds, as in createMultiSubdivisionGridForFunction()

  • startSubDiv: in the subdivision procedure, each region will start from an NxN uniform subdivision, before refining regions with more mass. If this parameter is a single integer number N, the same NxN subdivision will be used for each region. It can also be a list of numbers, to start with different uniform subdivisions for each region.

  • randomFraction: if this is None, the default from the constructor is used, but here it can be overridden. See the constructor’s documentation for an explanation of its meaning.

  • lensFilter: if specified, this function can be used to apply some kind of filtering on the lens model, in case lensOrLensInfo refers to a gravitational lens instance. The function will be called with three arguments plus the arguments specified in the lensFilterParams dictionary. The first three arguments are the lens model, the bottom-left corner of a region, and the top-right corner. The function should return another lens model.

  • lensFilterParams: a dictionary with extra arguments for the previous function.

  • lensInfoFilter: similar to lensFilter, in case a LensInfo object is used. In this case there is only one mandatory argument, the LensInfo object itself. Extra keyword arguments can be provided using the following lensInfoFilterParams dictionary. The function should return another LensInfo object.

  • lensInfoFilterParams: a dictionary with keyword arguments for the previous function.

  • excludeFunction: if specified, for each grid cell it will be called as excludeFunction(cellCenter, cellSize, True) for the initial uniform grids, and as excludeFunction(cellCenter, cellSize, False) for the next subdivision steps. If the function returns True then that particular cell will not be included in the final grid.

  • checkSubDivFunction: if specified, when a cell is considered to be subdivided, this function is called with as its two arguments the cell’s center and size. If it returns False, no subdivision may take place.

  • renderer: if a lens model is used as the lensOrLensInfo parameter, then for each region that’s present a mass map will be calculated. This specifies the renderer used for this calculation.

  • feedbackObject: the feedback mechanism used by the previous renderer.

getUniformGrid(subDiv, randomFraction=None, excludeFunction=None)

Based on the region information supplied by the constructor or by setRegionSize(), this subdivides the regions in a uniform way based on subDiv. If this is an integer number N, then each region will be subdivided into an NxN grid. Alternatively, this can be a list with one number per region, in case each region should be subdivided in a different way.

If randomFraction is None, the default from the constructor is used, but here it can be overridden. See the constructor’s documentation for an explanation of its meaning.

If excludeFunction is specified, for each grid cell it will be called as excludeFunction(cellCenter, cellSize, True), and if the function returns True then that particular cell will not be included in the final grid.

setRegionSize(regionSize=None, regionCenter=None, multiRegionInfo=None)

Allows you to update the regions that were set in the constructor. See the documentation there for the meaning of the parameters.

Core functions

grale.grid.createUniformGrid(size, center, axisSubDivisions, excludeFunction=None)

Creates a uniform grid, centered on the X,Y coordinates in center and with width and height specified by size. The generated grid will be have axisSubDivisions cells in X and Y directions.

If excludeFunction is specified, for each grid cell it will be called as excludeFunction(cellCenter, cellSize, True), and if the function returns True then that particular cell will not be included in the final grid.

grale.grid.createMultiUniformGrid(uniformRegionInfo, excludeFunction=None)

This is a generalization of createUniformGrid(), to work with different regions that should each be uniformly subdivided. The uniformRegionInfo parameter should be a list of dictionaries, each having keys "size", "center" and "axissubdiv", describing dimensions and subdivision of a particular region.

If excludeFunction is specified, for each grid cell it will be called as excludeFunction(cellCenter, cellSize, True), and if the function returns True then that particular cell will not be included in the final grid.

grale.grid.createSubdivisionGridForFunction(targetDensityFunction, size, center, minSquares, maxSquares, startSubDiv=1, excludeFunction=None, maxIntegrationSubDiv=256, keepLarger=False, checkSubDivFunction=None)

Creates a grid of which the cell density is based on the values provided by a function targetDensityFunction, and do the refinement in such a way that the resulting number of grid cells is within the specified bounds. This is the core function that’s used by createSubdivisionGrid() and createSubdivisionGridForFITS(), which themselves may me more straightforward to use for specific purposes.

Arguments:

  • targetDensityFunction: a function which will be called with a (Ny,Nx,2) shaped NumPy array, describing X,Y coordinates on a 2D grid. The function must return an (Ny, Nx) shaped NumPy array containing the densities at the specified coordinates. Note that because the algorithm below will numerically integrate cells in the grid, it is probably not a good idea to let this function return negative values.

  • size and center: specifies the center X,Y coordinates of the grid, as well as the grid’s width and height.

  • minSquares and maxSquares: stop looking for the required grid refinement when the total number of grid cells lies between these values.

  • startSubDiv: by default, a single, large grid cell will be subdivided until the required refinement has been reached. By setting this option to 5 for example, you’d start from a uniform 5x5 grid, of which each cell will be refined further.

  • excludeFunction: if specified, for each grid cell it will be called as excludeFunction(cellCenter, cellSize, True) for the initial uniform grid (see startSubDiv), and as excludeFunction(cellCenter, cellSize, False) for the next subdivision steps. If the function returns True then that particular cell will not be included in the final grid.

  • maxIntegrationSubDiv: to determine if a cell needs to be subdivided, the algorithm will integrate the contents numerically. This number specifies the maximum number of parts that are used for the entire size range. Smaller cells will be subdivided in fewer parts according to their size.

  • keepLarger: if True, after subdividing a grid cell, the original cell will also be kept in the list of cells.

  • checkSubDivFunction: if specified, when a cell is considered to be subdivided, this function is called with as its two arguments the cell’s center and size. If it returns False, no subdivision may take place.

Refinement algorithm: in a helper routine, each cell will be split into four smaller cells whenever the integrated value of the cell exceeds some threshold. The main function then iteratively looks for an appropriate threshold, so that the final number of cells lies within the desired bounds.

grale.grid.createMultiSubdivisionGridForFunction(targetDensityFunction, subdivRegionInfo, minSquares, maxSquares, excludeFunction=None, maxIntegrationSubDiv=256, keepLarger=False, checkSubDivFunction=None)

This is a generalization of createSubdivisionGridForFunction(), to allow the subdivision routine to work with several square regions at once. Most arguments are the same, but subdivRegionInfo now lists information about multiple regions.

Arguments:

  • targetDensityFunction: a function which will be called with a (Ny,Nx,2) shaped NumPy array, describing X,Y coordinates on a 2D grid. The function must return an (Ny, Nx) shaped NumPy array containing the densities at the specified coordinates. Note that because the algorithm below will numerically integrate cells in the grid, it is probably not a good idea to let this function return negative values.

  • subdivRegionInfo: This specifies the different square regions that will be subdivided. It should be a list of dictionaries with the following keys: "size", "center" and optionally "startsubdiv". The first two describe the region itself; if the last one (defaults to 1) has value N, the subdivision process starts from a uniform NxN grid.

  • minSquares and maxSquares: stop looking for the required grid refinement when the total number of grid cells (for all regions) lies between these values.

  • excludeFunction: if specified, for each grid cell it will be called as excludeFunction(cellCenter, cellSize, True) for the initial uniform grids (see "startsubdiv" keys in subdivRegionInfo), and as excludeFunction(cellCenter, cellSize, False) for the next subdivision steps. If the function returns True then that particular cell will not be included in the final grid.

  • maxIntegrationSubDiv: to determine if a cell needs to be subdivided, the algorithm will integrate the contents numerically. This number specifies the maximum number of parts that are used for the entire size range. Smaller cells will be subdivided in fewer parts according to their size.

  • keepLarger: if True, after subdividing a grid cell, the original cell will also be kept in the list of cells.

  • checkSubDivFunction: if specified, when a cell is considered to be subdivided, this function is called with as its two arguments the cell’s center and size. If it returns False, no subdivision may take place.

The refinement algorithm is still the same as in createSubdivisionGridForFunction(): in a helper routine, each cell will be split into four smaller cells whenever the integrated value of the cell exceeds some threshold. The main function then iteratively looks for an appropriate threshold, so that the final number of cells lies within the desired bounds.

grale.grid.createSubdivisionGridForFITS(fitsHDUEntry, centerRaDec, gridSize, gridCenter, minSquares, maxSquares, startSubDiv=1, excludeFunction=None, maxIntegrationSubDiv=256, keepLarger=False, ignoreOffset=True, useAbsoluteValues=True, checkSubDivFunction=None)

Creates a subdivision grid that’s based on an entry of a FITS file. It calls createSubdivisionGridForFunction() internally, where you can find the explanation of the algorithm used.

Arguments:

  • fitsHDUEntry: the FITS entry on which the subdivision grid should be based

  • centerRaDec: use these RA,Dec coordinates to recalculate the coordinates in the FITS file, i.e. that specific point will be associated to the new (0,0) coordinate.

  • gridSize: the width and height of the grid, will be used as the size parameter in createSubdivisionGridForFunction()

  • gridCenter: the center of the grid in the re-centered coordinates. Will be used as the center parameter in createSubdivisionGridForFunction().

  • minSquares, maxSquares, startSubDiv, excludeFunction, maxIntegrationSubDiv, keepLarger: see createSubdivisionGridForFunction()

  • ignoreOffset: adds or subtracts a value from the data so that the minimum value becomes zero.

  • useAbsoluteValues: set to False to allow negative values (probably not a good idea).

  • checkSubDivFunction: if specified, when a cell is considered to be subdivided, this function is called with as its two arguments the cell’s center and size. If it returns False, no subdivision may take place.

grale.grid.createMultiSubdivisionGridForFITS(fitsHDUEntry, centerRaDec, subdivRegionInfo, minSquares, maxSquares, excludeFunction=None, maxIntegrationSubDiv=256, keepLarger=False, ignoreOffset=True, useAbsoluteValues=True, checkSubDivFunction=None)

This is a generalization of createSubdivisionGridForFITS(), calls createMultiSubdivisionGridForFunction() internally, where you can find the explanation of the algorithm used.

Arguments:

  • fitsHDUEntry: the FITS entry on which the subdivision grid should be based

  • centerRaDec: use these RA,Dec coordinates to recalculate the coordinates in the FITS file, i.e. that specific point will be associated to the new (0,0) coordinate.

  • subdivRegionInfo, minSquares, maxSquares, excludeFunction, maxIntegrationSubDiv, keepLarger and checkSubDivFunction: see createMultiSubdivisionGridForFunction()

  • ignoreOffset: adds or subtracts a value from the data so that the minimum value becomes zero.

  • useAbsoluteValues: set to False to allow negative values (probably not a good idea).

grale.grid.createSubdivisionGrid(size, center, lensInfo, minSquares, maxSquares, startSubDiv=1, excludeFunction=None, maxIntegrationSubDiv=256, keepLarger=False, ignoreOffset=True, useAbsoluteValues=True, checkSubDivFunction=None)

Creates a subdivision grid that’s based on the specified gravitational lens information. Internally, the function createSubdivisionGridForFunction() is called, where you can find the explanation of the algorithm used.

Arguments:

  • size: the width and height of the grid, will be used as the size parameter in createSubdivisionGridForFunction()

  • center: the center of the grid in the re-centered coordinates. Will be used as the center parameter in createSubdivisionGridForFunction().

  • lensInfo: information about the gravitational lens, see LensInfo (or DensInfo).

  • minSquares, maxSquares, startSubDiv, excludeFunction, maxIntegrationSubDiv, keepLarger: see createSubdivisionGridForFunction()

  • ignoreOffset: adds or subtracts a value from the data so that the minimum value becomes zero.

  • useAbsoluteValues: set to False to allow negative values (probably not a good idea).

  • checkSubDivFunction: if specified, when a cell is considered to be subdivided, this function is called with as its two arguments the cell’s center and size. If it returns False, no subdivision may take place.

grale.grid.createMultiSubdivisionGrid(subdivRegionInfo, lensInfo, minSquares, maxSquares, excludeFunction=None, maxIntegrationSubDiv=256, keepLarger=False, ignoreOffset=True, useAbsoluteValues=True, checkSubDivFunction=None)

This is a generalization of createSubdivisionGrid(), to work with several square regions at the same time. It creates a subdivision grid that’s based on the provided lens information; internally, the function createMultiSubdivisionGridForFunction() is called, where you can find the explanation of the algorithm used.

Arguments:

  • subdivRegionInfo: specifies the regions, will be passed as the same parameter of createMultiSubdivisionGridForFunction().

  • lensInfo: information about the gravitational lens, can either be a single LensInfo (or DensInfo) object, or a list of these, one for each region in the subdivRegionInfo list.

  • minSquares, maxSquares, excludeFunction, maxIntegrationSubDiv, keepLarger and checkSubDivFunction: see createSubdivisionGridForFunction().

  • ignoreOffset: adds or subtracts a value from the data so that the minimum value becomes zero.

  • useAbsoluteValues: set to False to allow negative values (probably not a good idea).

grale.grid.fractionalGridToRealGrid(grid)

Transforms the specified grid, which uses a grid center and fractional sizes and centers for the cells, to a straighforward list of cells, each having a regular center and size.

grale.grid.fitMultiplePlummerLens(gridCells, Dd, targetDensityFunction, sizeFactor=1.7)

Fits a mass distribution based on multiple Plummer base functions that are arranged according to specified grid cells, to a specific target function. For each cell, the center of the cell and the centers of each side will be used to evaluate the target function. A least squares approach is then used to find the weigths of the basis functions that minimize the differences at these points.

The function returns an instance of the MultiplePlummerLens class.

Examples can be found in the notebook fittest.ipynb.

Arguments:

  • gridCells: the grid to base the layout of the Plummer basis functions on

  • Dd: the angular diameter distance to be used when creating the MultiplePlummerLens instance.

  • targetDensityFunction: a function which will be called with a (Ny,Nx,2) shaped NumPy array, describing X,Y coordinates on a 2D grid. The function must return an (Ny, Nx) shaped NumPy array containing the densities at the specified coordinates. Note that because the algorithm below will numerically integrate cells in the grid, it is probably not a good idea to let this function return negative values.

  • sizeFactor: a factor to be used to convert the size of a grid cell to the width of the Plummer basis function. For a cell with a size of 1 arcsec, a Plummer width of 1.7 arcsec will be used.