The desimodel package/API¶
desimodel¶
A package for providing machine-readable data about the DESI focal plane and other hardware designs to simulations.
- class desimodel.fastfiberacceptance.FastFiberAcceptance(filename=None)[source]¶
This class reads an input fits file generated with specsim.fitgalsim ($DESIMODEL/data/throughput/galsim-fiber-acceptance.fits) and instanciates RegularGridInterpolator objects for 2D and 3D interpolation of the pre-computed galsim fiber acceptance as a function of sigma (atmosphere+telescope blur, in um on focal surface), fiber offset from source (in um on focal surface), and half light radius (in arcsec) from extended source. The average and rms interpolation function for POINT,DISK and BULGE profiles are loaded.
- rms(source, sigmas, offsets=None, hlradii=None)[source]¶
returns fiber acceptance fraction rms for the given source,sigmas,offsets
- Parameters:
source (string) – POINT, DISK or BULGE for point source, exponential profile or De Vaucouleurs profile
sigmas (np.array) – arbitrary shape, values of sigmas in um for the PSF due to atmosphere and telescope blur
- Optional:
hlradii (np.array) : same shape as sigmas, half light radius in arcsec for source offsets (np.array) : same shape as sigmas, values of offsets on focal surface between fiber and source, in um
Returns np.array with same shape as input
- value(source, sigmas, offsets=None, hlradii=None)[source]¶
returns the fiber acceptance for the given source,sigmas,offsets
- Parameters:
source (string) – POINT, DISK or BULGE for point source, exponential profile or De Vaucouleurs profile
sigmas (np.array) – arbitrary shape, values of sigmas in um for the PSF due to atmosphere and telescope blur
offsets (np.array) – same shape as sigmas, values of offsets on focal surface between fiber and source, in um
- Optional:
hlradii (np.array) : same shape as sigmas, half light radius in arcsec for source
Returns np.array with same shape as input
desimodel.focalplane.fieldrot¶
Routines to estimate the field rotation in the DESI focal plane. The rotation angle is defined in DESI-5190.
The CS5 system is defined in DESI-481. It is a plane tangent to the focal plane surface, attached to the petals. It has the axis X pointing to the physical east (and thus due to the mirror, sees targets on the sky to the physical west = increasing HA, decreasing RA), Y to the physical south (and thus due to the mirror, sees targets on the sky to the physical north = increasing Dec), and Z towards the mirror.
The ICRS is the sky coordinate system of the DESI target catalogs, the same as Gaia astrometry. RA Dec will always be in the ICRS system.
The Field rotation angle ‘Theta’ measures the rotation of the star images in the CS5 plane (not a rotation of the instrument, opposite sign!), tangent to the focal plane, assumed for assigning fibers.
Theta=0 corresponds to zero rotation after the coordinate transformation from the ICRS RA,Dec sky coordinates to the CS5, with Y pointing to the north (increasing Dec).
Theta is increasing from North to East (or from X(West) to Y(North)).
The DESI field rotation is due to a combination of precession, aberration, and polar misalignement and general mount imperfections.
Here we will just consider the most important terms.
A good fraction of the code below if from Mike Lampton, imported in desimodel by Julien Guy.
- desimodel.focalplane.fieldrot.field_rotation_angle(ra, dec, mjd, use_astropy=False)[source]¶
precessiom, etc: https://desi.lbl.gov/DocDB/cgi-bin/private/ShowDocument?docid=4957
- Parameters:
ra (Right ascension of center of focal plane in ICRS, in degrees) –
dec (Declination of center of focal plane in ICRS, in degrees) –
mjd (Modified Julian Date, decimal number, of the observation) –
- Return type:
Field rotation angle, in degrees
- desimodel.focalplane.fieldrot.rotation_angle(x1, y1, x2, y2)[source]¶
returns the angle from (x1,y1) to (x2,y2), in deg
desimodel.focalplane.geometry¶
Dimensions and coordinate system transforms for the DESI focal plane.
- class desimodel.focalplane.geometry.FocalPlane(ra=0.0, dec=0.0)[source]¶
A class for modeling the DESI focal plane and converting between focal plane coordinates (in mm) and RA, Dec on the sky (in degrees). Provides utility functions for mapping which positioners cover which (RA, Dec) or (x, y) locations and vice versa.
- Parameters:
ra (
float
) – Initialize DESI focal plane model with the telescope pointing at (ra, dec) in degrees.dec (
float
) – Initialize DESI focal plane model with the telescope pointing at (ra, dec) in degrees.NOTE (this class is deprecated (or should be further expanded), but) –
that (I'm not removing it yet in order to not arbitrarily break code) –
it. (might be using) –
- radec2pos(ra, dec)[source]¶
Identify which positioners cover (ra, dec).
If ra, dec are floats, return an array of positioner IDs that cover it. The array could be empty if no positioner covers that location.
If ra, dec are numpy arrays, return a list of arrays. The ith element is an array of positioner IDs that cover (ra[i], dec[i]).
Warning
This method is not implemented!
- radec2xy(ra, dec)[source]¶
Convert (RA, Dec) in degrees to (x, y) in mm on the focal plane given the current telescope pointing.
If RA and Dec are floats, returns a tuple (x, y) of floats If RA and Dec are numpy arrays, returns a tuple (x, y) of numpy arrays
- Parameters:
ra (
float
ornumpy.ndarray
) – Sky position.dec (
float
ornumpy.ndarray
) – Sky position.
- Returns:
A tuple containing the (x, y) coordinates in mm.
- Return type:
tuple()
- set_tele_pointing(ra, dec)[source]¶
Set telescope pointing to (RA, Dec) in degrees.
- Parameters:
ra –
dec (
float
) – Telescope pointing in degrees.
- xy2pos(x, y)[source]¶
Identify which positioners cover (x, y).
Warning
This method is not implemented!
- desimodel.focalplane.geometry._extrapolate_r_s(r, s)[source]¶
Utility function for xy2qs and qs2xy; returns new r, s with extrapolations to 0 and max(r)+10 mm.
- desimodel.focalplane.geometry.fiber_area_arcsec2(x, y)[source]¶
Returns area of fibers at (x, y) in arcsec^2.
- desimodel.focalplane.geometry.get_radius_deg(x, y)[source]¶
Returns the radius in degrees given x, y coordinates using the platescale data.
- desimodel.focalplane.geometry.get_radius_mm(theta)[source]¶
Returns an array of radii in mm given an array of radii in degrees using the platescale data relative to the center of the focal plane as (0,0). Supports scalar and vector inputs.
- desimodel.focalplane.geometry.get_tile_radius_deg()[source]¶
Returns maximum radius in degrees covered by the outermost positioner.
- desimodel.focalplane.geometry.get_tile_radius_mm()[source]¶
Returns maximum radius in mm covered by the outermost positioner.
- desimodel.focalplane.geometry.qs2xy(q, s)[source]¶
angular q,s on curved focal surface -> focal tangent plane x,y
- Parameters:
q – angle in degrees
s – focal surface radial distance in mm
Returns (x, y) cartesian location on focal tangent plane in mm
Notes: (x,y) are in the “CS5” DESI coordinate system tangent plane to the curved focal surface. q is the radial angle measured counter-clockwise from the x-axis; s is the radial distance along the curved focal surface; it is not sqrt(x**2 + y**2). (q,s) are the preferred coordinates for the DESI focal plane hardware engineering team.
- desimodel.focalplane.geometry.radec2xy(telra, teldec, ra, dec)[source]¶
Returns arrays of the x, y positions of given celestial objects on the focal plane given an arbitrary telescope pointing in RA and Dec and arrays of the ra and dec of celestial objects in the sky.
- Parameters:
- Returns:
The x, y positions corrsponding to ra, dec.
- Return type:
Notes
Implements the Haversine formula.
- desimodel.focalplane.geometry.xy2qs(x, y)[source]¶
Focal tangent plane x,y -> angular q,s on curved focal surface
- Parameters:
x – cartesian location on focal tangent plane in mm
y – cartesian location on focal tangent plane in mm
Returns (q, s) where q=angle in degrees; s=focal surface radial dist [mm]
Notes: (x,y) are in the “CS5” DESI coordinate system tangent plane to the curved focal surface. q is the radial angle measured counter-clockwise from the x-axis; s is the radial distance along the curved focal surface; it is not sqrt(x**2 + y**2). (q,s) are the preferred coordinates for the DESI focal plane hardware engineering team.
- desimodel.focalplane.geometry.xy2radec(telra, teldec, x, y)[source]¶
Returns the new RA and Dec of an x, y position on the focal plane in the sky given an arbitrary telescope pointing in RA and Dec.
- Parameters:
- Returns:
The RA, Dec corresponding to x, y.
- Return type:
desimodel.focalplane.gfa¶
Guide-Focus-Alignment location routines
- desimodel.focalplane.gfa.get_gfa_targets(targets, rfluxlim=1000, tiles=None, scale=1.0)[source]¶
This function takes a table of targets, as well as optional parameters including a minimum flux in the r-band, a list of tiles, and a buffer in arcseconds and returns a table of targets on the GFA satisfying a minimum flux_r
- Parameters:
targets (Table) – Table columns RA, DEC, FLUX_R.
rfluxlim (
float
, optional) – r-band flux limit; default 1000 = rmag 15.tiles (Table, optional) – Table of tiles, default to
desimodel.io.load_tiles()
.scale (
float
, optional) – Scale factor for GFA size to allow slightly off the edge targets
- Returns:
A subset of input targets with additional columns: TILEID: (integer) DESI tile ID; GFA_LOC: (integer) GFA location [0-9].
- Return type:
Table
Notes
The same target could be repeated with different TILEID, GFA_LOC.
The function returns an empty Table if no targets are on any GFAs or of sufficient brightness.
- desimodel.focalplane.gfa.on_gfa(telra, teldec, ra, dec, scale=1.0)[source]¶
Checks if a target is on any of the 10 GFAs given telra, teldec and an array of ra and dec pointings, as well as a parameter for degrees of tolerance one would like to allow.
- Parameters:
telra (
float
) – The telescope’s arbitrary RA pointing.teldec (
float
) – The telescope’s arbitrary Dec pointing.ra (array-like) – An array of RA values for locations in the sky.
dec (array-like) – An array of Dec values for locations in the sky.
scale (
float
, optional) – Scale factor for GFA size to allow slightly off the edge targets
- Returns:
An array of the same length as input ra, giving the GFA_LOC that each (ra, dec) is on. -1 means not on a GFA.
- Return type:
array
- desimodel.focalplane.gfa.on_tile_gfa(tileid, targets, scale=1.0)[source]¶
This function takes a tileid, a table of targets, and an optional buffer_arcsec parameter to return the indices of targets lying on the GFA as well as the GFA locations from 0-9.
desimodel.focalplane.sim¶
Tools for generating simulated random distortion fields.
- desimodel.focalplane.sim.generate_random_centroid_offsets(rms_offset=8.0, seed=123)[source]¶
Generate random centroid offsets.
Calls
generate_random_vector_field()
to generate offsets with a power spectrum exponent of -1 in the expected format.The arrays in the files
$DESIMODEL/data/throughput/DESI-0347_static_offset_<n>.fits
were generated by this method with seeds n=1,2,3.The default RMS offset value is taken from cell B52 of the Throughput sheet from DESI-0347-v13, labeled “FVC corrector optics figure error”.
- Parameters:
rms_offset (
astropy.Quantity
instance.) – RMS that the generated offsets should have, including units.seed (
int
) – Random number seed to use. Generated offsets should be portable across python versions and platforms.
- Returns:
Tuple dx, dy of centroid offset arrays with units.
- Return type:
- desimodel.focalplane.sim.generate_random_vector_field(rms, exponent, n, seed=None, smoothing=0.02)[source]¶
Generate a pair dx, dy of 2D Gaussian random field.
The random field is generated with a power spectrum P(k) ~ r ** exponent and normalized to the specified RMS value. Smoothing is applied to minimize grid artifacts.
- Parameters:
rms (
float
or astropy quantity) – Desired RMS of the generated field values.exponent (
float
) – Exponent of the power spectrum scaling with radius.n (
int
) – Size of the generated array along each axis.seed (
int
) – Random number seed to use. Generated fields should be portable across python versions and platforms.smoothing (
float
) – Length scale for smoothing the generated field expressed as a fraction of the full width of the field. Implemented as a Gaussian convolution. No smoothing is applied when smoothing is zero.
- Returns:
Tuple dx, dy of 2D arrays containing the generated Gaussian random field values. Arrays will have the same units as the rms parameter, if any.
- Return type:
desimodel.footprint¶
Utility functions for working with the DESI footprint.
- desimodel.footprint._embed_sphere(ra, dec)[source]¶
Embed ra, dec to a uniform sphere in three dimensions.
- desimodel.footprint.find_points_in_tiles(tiles, ra, dec, radius=None)[source]¶
Return a list of indices of points that are within each provided tile(s).
This function is optimized to query a lot of points with relatively few tiles.
radius is in units of degrees. The return value is an array of lists that contains the index of points that are in each tile. The indices are not sorted in any particular order.
if tiles is a scalar, a single list is returned.
default radius is from desimodel.focalplane.get_tile_radius_deg()
- desimodel.footprint.find_points_radec(telra, teldec, ra, dec, radius=None)[source]¶
Return a list of indices of points that are within a radius of an arbitrary telra, teldec.
This function is optimized to query a lot of points with a single telra and teldec.
radius is in units of degrees. The return value is a list that contains the index of points that are in each tile. The indices are not sorted in any particular order.
if tiles is a scalar, a single list is returned.
default radius is from desimodel.focalplane.get_tile_radius_deg()
Note: This is simply a modified version of find_points_in_tiles, but this function does not know about tiles.
- desimodel.footprint.find_tiles_over_point(tiles, ra, dec, radius=None)[source]¶
Return a list of indices of tiles that covers the points.
This function is optimized to query a lot of points. radius is in units of degrees. The return value is an array of list objects that are the indices of tiles that cover each point.
The indices are not sorted in any particular order.
if ra, dec are scalars, a single list is returned.
default radius is from desimodel.focalplane.get_tile_radius_deg()
- desimodel.footprint.get_tile_radec(tileid)[source]¶
Get the coordinates of a tile.
- Parameters:
tileid (int) – ID of a tile.
- Returns:
(ra, dec) in degrees for the requested tileid.
- Return type:
- Raises:
ValueError – If tileid is not in list of known tiles.
- desimodel.footprint.is_point_in_desi(tiles, ra, dec, radius=None, return_tile_index=False)[source]¶
If a point (ra, dec) is within radius distance from center of any tile, it is in DESI.
- Parameters:
tiles (Table-like) – The output of
desimodel.io.load_tiles()
, or a similar Table.ra (scalar or array-like) – Right Ascension in degrees.
dec (scalar or array-like) – Declination in degrees. The size of dec must match the size of ra.
radius (float, optional) – Tile radius in degrees; if None use
desimodel.focalplane.get_tile_radius_deg()
.return_tile_index (bool, optional) – If
True
, return the index of the nearest tile in tiles array.
- Returns:
Return
True
if points given by ra, dec lie in the set of tiles.
Notes
This function is optimized to query a lot of points.
- desimodel.footprint.pass2program(tilepass, surveyops=False)[source]¶
Converts integer tile pass number to string program name.
- Parameters:
tilepass (int or int array) – tiling pass number.
surveyops (bool):
True
to look for tiles in $DESI_SURVEYPOPS.- Returns:
Program name for each pass (str or list of str).
- desimodel.footprint.pix2tiles(nside, pixels, tiles=None, radius=None)[source]¶
Returns subset of tiles that overlap the list of pixels.
- Parameters:
nside (int) – HEALPix nside,
2**k
where 0 < k < 30.pixels (array-like) – Array of integer pixels using nested numbering scheme.
tiles (Table-like, optional) – Table-like with RA,DEC columns; or
None
to use all DESI tiles fromdesimodel.io.load_tiles()
.radius (float, optional) – Tile radius in degrees; if None use
desimodel.focalplane.get_tile_radius_deg()
.
- Returns:
Table of tiles that cover these pixels.
TODO: add support for tiles as integers or list/array of integer TILEIDs.
- desimodel.footprint.pixweight(nside, tiles=None, radius=None, precision=0.01, outfile=None, outplot=None)[source]¶
Create an array of the fraction of each pixel that overlaps the passed tiles.
- Parameters:
nside (int) – HEALPix nside,
2**k
where 0 < k < 30.tiles (Table-like, optional) – Table-like with RA,DEC columns; or
None
to use all DESI tiles fromdesimodel.io.load_tiles()
.radius (float, optional) – Tile radius in degrees; if None use
desimodel.focalplane.get_tile_radius_deg()
.precision (float, optional) – Approximate precision at which to calculate the area of pixels that partially overlap the footprint in SQUARE DEGREES (e.g. 0.01 means precise to 0.01 sq. deg., or 36 sq. arcmin.). Lower numbers mean better precision.
outfile (str, optional) – Write the pixel->weight array to the file passed as outfile (could be full directory path + file).
outplot (str, optional) – Create a plot named outplot (pass a name for a plot in the current directory, a full path for a plot in a different directory). This is passed to matplotlib.pyplot’s savefig routine.
- Returns pixweight:
An array of the weight for each pixel at the passed nside. The weight is the fracion of the pixel that overlaps the passed tiles: WEIGHT=1 for the pixel is entirely contained in the tiles; WEIGHT=0 for the pixel is entirely outside of the tiles; 0 < WEIGHT < 1 for a pixel that overlaps the tiles. The index of the array is the HEALPixel integer.
Notes
It is sufficient to create the weights at a suitably high nside, say nside=256 (0.052456 sq. deg. per pixel) as pixel numbers at lower nsides can be obtained by integer division by powers of 4, e.g. pix_@_nside_128 = pix@nside_256//4 and fractional weights at lower nsides are the mean of the 4 pixels at the higher nside
desimodel.io.load_pixweight()
can downsample the array to lower nsides.
- desimodel.footprint.program2pass(program)[source]¶
Convert string program name to tile passes for that program.
- Parameters:
program (str for str array) – program name, e.g. DARK, BRIGHT, or GRAY.
- Returns:
List of integer passes that cover that program, or list of lists if input was array-like.
- desimodel.footprint.radec2pix(nside, ra, dec)[source]¶
Convert ra, dec to nested pixel number.
- Parameters:
- Returns:
Array of integer pixel numbers using nested numbering scheme.
Notes
This is syntactic sugar around:
hp.ang2pix(nside, ra, dec, lonlat=True, nest=True)
but also works with older versions of healpy that didn’t have lonlat yet.
- desimodel.footprint.tileids2pix(nside, tileids, radius=None, per_tile=False)[source]¶
Like
tiles2pix()
, but accept integer tileid or list of tileids instead of table of tiles.
- desimodel.footprint.tiles2fracpix(nside, step=1, tiles=None, radius=None, fact=128)[source]¶
Returns a sorted array of just the fractional pixels that overlap the tiles.
- Parameters:
nside (int) – HEALPix nside,
2**k
where 0 < k < 30.step (int, optional) – The number of integration steps around the edges of a HEALPix pixel.
step=1
means just the pixel vertices.step=2
means the vertices and the corners and the points halfway between the vertices. See also the HEALPix boundary document .tiles (Table-like, optional) – Table-like with RA,DEC columns; or
None
to use all DESI tiles fromdesimodel.io.load_tiles()
.radius (float, optional) – Tile radius in degrees; if
None
usedesimodel.focalplane.get_tile_radius_deg()
.fact (int, optional) – Factor healpy uses to resolve pixel overlaps. When this is large there are fewer false positives at the expense of run time (although
fact=2**8
seems fast). Must be a power of 2.
- Returns:
Integer array of pixel numbers that cover these tiles, excluding pixels that fully overlap the tiles (i.e., just pixels that partially overlap the tiles). The integers are sorted.
Notes
There are potentially malicious cases where a pixel just brushes a tile, such that there is a very small area where the pixel overlaps the tile. To guard against these case, call this function with progressively larger step values until it converges.
- desimodel.footprint.tiles2pix(nside, tiles=None, radius=None, per_tile=False, fact=128)[source]¶
Returns sorted array of pixels that overlap the tiles.
- Parameters:
nside (int) – HEALPix nside,
2**k
where 0 < k < 30.tiles (Table-like, optional) – tiles with columns RA,DEC or TILERA,TILEDEC, or None to load
desimodel.io.load_tiles()
(deprecated)radius (float, optional) – tile radius in degrees; if
None
usedesimodel.focalplane.get_tile_radius_deg()
.per_tile (bool, optional) – If
True
, return a list of arrays of pixels per tile.fact (int, optional) – Factor healpy uses to resolve pixel overlaps. When this is large there are fewer false positives at the expense of run time (although
fact=2**8
seems fast). Must be a power of 2.
- Returns:
Integer array of pixel numbers that cover these tiles; or if per_tile is True, returns list of arrays such that
pixels[i]
is an array of pixel numbers coveringtiles[i]
.
desimodel.inputs¶
Code for working with raw input data to the DESI model data.
desimodel.inputs.ci¶
Utilities for updating Commissioning Instrument corners in data/focalplane/ci-corners.ecsv.
- desimodel.inputs.ci.update()[source]¶
Update $DESIMODEL/data/focalplane/ci-corners.ecsv from DESI-4633v11
desimodel.inputs.docdb¶
Utility functions for working with DocDB files.
- desimodel.inputs.docdb._xls_col2int(col)[source]¶
Convert column string name to index, starting at 0
e.g. A -> 0, B -> 1, … Z -> 25, AA -> 26, AB -> 27
- desimodel.inputs.docdb.download(docnum, docver, filename, outdir=None, overwrite=False)[source]¶
Downloads and writes outdir/DESI-{docnum}v{docver}-{filename}
- Parameters:
docnum – integer DocDB number
docver – integer version number
filename – string filename within that DocDB entry
- Options:
outdir: output directory; default $DESIMODEL/data/inputs/docdb/ overwrite: overwrite pre-existing file
- Returns:
path to output file written
Notes
only supports python3
creates outdir if needed
prepends DESI-{docnum}v{docver} to {filename} even if filename already starts with that (in DocDB, some do and some don’t…)
- desimodel.inputs.docdb.xls_read_col(filename, sheetname, column, firstrow, lastrow, dtype=None)[source]¶
Read Excel file column from firstrow to lastrow
- Parameters:
- Options:
dtype: convert output to this numpy dtype
Returns numpy array of data
Example
B5:B10 -> column=’B’, firstrow=5, lastrow=10 -> length 6 array
- desimodel.inputs.docdb.xls_read_row(filename, sheetname, rownum, firstcol, lastcol, dtype=None)[source]¶
Read Excel file row from firstcol to lastcol
- Parameters:
- Options:
dtype: convert output to this numpy dtype
Returns numpy array of data
Example
B5:D5 -> rownum=5, firstcol=’B’, lastcol=’D’ -> length 3 array
desimodel.inputs.fiberpos¶
Utilities for updating positioner to fiber mapping.
- desimodel.inputs.fiberpos.update(testdir=None, seed=2)[source]¶
Update positioner to fiber number mapping from DocDB
- Options:
- testdir: if not None, write files here instead of
$DESIMODEL/data/footprint/fiberpos*
- seed:
integer random number seed for randomization within a cartridge
Writes testdir/fiberpos* or $DESIMODEL/data/focalplane/fiberpos*
- desimodel.inputs.fiberpos.write_text_fiberpos(filename, fiberpos)[source]¶
Writes a fiberpos table to filename, maintaining backwards compatibility with the original fiberpos.txt format
- Parameters:
filename – output file name string
fiberpos – astropy Table of fiber positions
desimodel.inputs.focalplane¶
Utilities for constructing a focalplane model.
- desimodel.inputs.focalplane.create(testdir=None, posdir=None, fibermaps=None, petalloc=None, startvalid=None, fillfake=False, fakeoffset=False, fakefiberpos=False, reset=False)[source]¶
Construct DESI focalplane and state files.
- This function gathers information from the following sources:
Petal verification files on DocDB
Positioner device configuration files (e.g. from svn).
DESI-0530, to get the mapping from device ID to device type as well as the nominal device X/Y offsets on petal 0 (for fillfake option).
Exclusion configobj files in $DESIMODEL/data/focalplane.
- Parameters:
testdir (str) – Override the output directory for testing.
posdir (str) – Directory containing the many positioner conf files. If None, simulate identical, nominal positioners. A None value will force fillfake=True.
fibermaps (list) – Override list of tuples (DocDB number, DocDB version, DocDB csv file) of where to find the petal mapping files.
petalloc (dict) – Mapping of petal ID to petal location.
startvalid (str) – The first time when this focalplane model is valid. ISO 8601 format string.
fillfake (bool) – If True, fill missing device locations with fake positioners with nominal values for use in simulations.
fakeoffset (bool) – If True, artificially sets the theta / phi angle offsets to zero. This replicates the behavior of legacy fiberassign and should only be used for testing.
fakefiberpos (bool) – If True, ignore the real fibermaps and load the old fiberpos file to get the mapping. Only useful for testing.
reset (bool) – If True, ignore all previous focalplane models and start with all positioners “good”. Default propagates the state of most recent model, after verifying that the positioners are the same.
- Returns:
None
- desimodel.inputs.focalplane.devices_from_fiberpos(fp)[source]¶
Populate focalplane properties from a fiberpos file.
This is only used for testing consistency with the previous fiberpos files. It should not be used for work with the real instrument. The focalplane properties are modified in place.
- Parameters:
fp (dict) – The focalplane dictionary.
- Returns:
None
- desimodel.inputs.focalplane.devices_from_files(fp, posdir=None, fillfake=False, fakeoffset=False, fibermaps=None)[source]¶
Populate focalplane properties from information in files.
This populates the focalplane with device information gathered from the “pos_settings” files in svn and from the “Petal verification” files on DocDB.
The focalplane dictionary is modified in place.
- Parameters:
fp (dict) – The focalplane dictionary.
posdir (str) – Directory containing the many positioner conf files.
fillfake (bool) – If true, fill missing POS and ETC locations with a fake nominal positioner.
fakeoffset (bool) – If true, use theta / phi offsets that matched very old versions of fiberassign.
fibermaps (list) – (optional) Override list of tuples (DocDB number, DocDB version, DocDB csv file) of where to find the petal mapping files.
- Returns:
None
desimodel.inputs.focalplane_sync¶
Tools for checking and synchronizing focalplane state to online system.
- desimodel.inputs.focalplane_sync.convert_fp_calibs(fpcal, sim=False)[source]¶
Convert the online system information.
This returns a tuple containing the focalplane, the current state, and the set of unique exclusion polygons found in the file.
- Parameters:
fpcal (Table) – The table loaded from a dump from the online system.
sim (bool) – If True, clear all transient state issues and set hardware to be as “good as possible”, for use in simulations.
- Returns:
- The (focalplane, state, exclusions, time string) loaded from
the cal file.
- Return type:
(tuple)
- desimodel.inputs.focalplane_sync.create_from_calibs(calib_file, out_dir=None, reset=False, sim_good=False, commit=False, test=False, fibermaps=None)[source]¶
Construct a DESI focalplane from a calibration dump.
This uses a dump from the online system and compares it to the current latest focalplane model and state.
- Parameters:
calib_file (str) – Path to the calibration dump.
out_dir (str) – Override the output directory for testing. Default writes to $DESIMODEL/data/focalplane/
reset (bool) – If True, ignore the current focalplane model and create a new model from this calibration dump. Default compares the new focalplane to the old and looks for changes in device state. These changes are appended to the existing log.
sim_good (bool) – If True, clear all transient state issues and set hardware to be as “good as possible”, for use in simulations.
commit (bool) – If True, attempt to commit the result.
test (bool) – If True, perform all operations but do not update any files.
fibermaps (list) – Override list of tuples (DocDB number, DocDB version, DocDB csv file) of where to find the petal mapping files.
- Returns:
None
- desimodel.inputs.focalplane_sync.load_fp_calibs(path)[source]¶
Load data dumped from the online system.
desimodel.inputs.focalplane_utils¶
Helpers for constructing a focalplane model.
- desimodel.inputs.focalplane_utils.compute_theta_phi_range(phys_t, phys_p)[source]¶
Compute the min/max range about the initial offset.
Based on the “full_range” defined in plate_control/petal/posmodel.py
- desimodel.inputs.focalplane_utils.create_device()[source]¶
Create an empty device property dictionary.
- desimodel.inputs.focalplane_utils.create_nominal(petal_loc)[source]¶
Create a nominal focalplane layout.
This uses DocDB 0530 to construct a nominal focalplane. All positioner devices are assigned to their nominal X/Y locations, nominal theta / phi offsets and ranges, and nominal arm lengths.
Quantities not specified in 0530, such as physical petal and device IDs, are set to -1.
The input petal_loc dictionary is required, and only petal IDs in this dictionary will be created.
Note: The X/Y offsets used are those relative to the petal when placed at location 3. After modifying these with data from other sources, the final offsets are rotated into place.
- desimodel.inputs.focalplane_utils.create_tables(n_fp_rows, n_state_rows=None)[source]¶
Create empty focalplane and state tables.
This function keeps the construction of the table schema in a single place that can be used across the code.
- desimodel.inputs.focalplane_utils.device_compare(fpold, fpnew, check)[source]¶
Compare two sets of focalplane device properties.
- Parameters:
fpold (Table) – The original device properties.
fpnew (Table) – The new device properties.
check (list) – The column names to check for equality.
- Returns:
- A dictionary containing the differences. The keys are
the LOCATION value, and the value is a dict with “old” and “new” keys that contain the table rows that differ.
- Return type:
(dict)
- desimodel.inputs.focalplane_utils.device_loc_to_type(loc)[source]¶
Get the fixed, hardcoded device type for a device location.
- desimodel.inputs.focalplane_utils.device_printdiff(diff)[source]¶
Print a diff dictionary created with device_compare().
- desimodel.inputs.focalplane_utils.exclusions_equal(ex1, ex2)[source]¶
Return True if the two polygons are equal, else False
- desimodel.inputs.focalplane_utils.load_petal_fiber_map(existing=None, fibermaps=None)[source]¶
Loads info from petal verification files.
This loads the petal verification files from DocDB and populates a dictionary of properties.
- Parameters:
- Returns:
- A dictionary of dictionaries with the device location info
for every petal ID.
- Return type:
(dict)
- desimodel.inputs.focalplane_utils.propagate_state(state, excl, oldstate, oldexcl)[source]¶
Propagate state to a new focalplane model.
This takes a new state and exclusions and sets this new state to be the same as the old one for all locations that are specified in the oldstate. Any exclusions not defined in the new dictionary are copied from the old.
This function assumes that the old and new focalplane models have already been verified to be identical…
- desimodel.inputs.focalplane_utils.restricted_positioner_phi(radius, theta_arm, phi_arm, offset_p, min_p, max_p)[source]¶
Compute the MIN_P angle needed to restrict positioner reach.
Given the positioner arm lengths, desired maximum reach, and PHI offset and min / max, compute the new minimum phi angle needed to keep the positioner within the retracted radius.
- Parameters:
- Returns:
The restricted MIN_P value.
- Return type:
(float)
- desimodel.inputs.focalplane_utils.rotate_petals(fp)[source]¶
Rotate the X/Y offsets according to petal location.
The X / Y offsets of each device are rotated to the petal location for that device. The focalplane dictionary is modified in place.
- Parameters:
fp (dict) – The focalplane dictionary.
- Returns:
None
- desimodel.inputs.focalplane_utils.update_exclusions(excl, paths=[])[source]¶
Update exclusion polygons in a focalplane model.
desimodel.inputs.gfa¶
Utilities for updating GFA data.
- desimodel.inputs.gfa.build_gfa_table(testdir=None)[source]¶
Builds the GFA table given the data from DESI-0530-v14 Excel spreadsheet and writes an .ecsv file using the astropy table library.
The GFA corners come from the P1-P4 “Reference projection of active area” in rows 26-29 of columns C-E of DESI-0530-v14.
The saved table has columns PETAL,CORNER,X,Y,Z,Q,S,RADIUS_DEG.
- Parameters:
testdir – If not None, write files here instead of standard locations under $DESIMODEL/data/
desimodel.inputs.throughput¶
Utilities for updating throughput model.
- desimodel.inputs.throughput.get_waveminmax(psffile)[source]¶
return wmin, wmax as taken from the header of a PSF file, e.g. $DESIMODEL/data/specpsf/psf-b.fits
- desimodel.inputs.throughput.load_fiberinput(filename)[source]¶
Load fiberinput as calculated by fiberloss.py
- Parameters:
filename – fiberloss input file, e.g. $DESIMODEL/data/throughput/fiberloss-elg.dat
Returns InterpolatedUnivariateSpline instance.
- desimodel.inputs.throughput.load_spec_throughputs(filenames, columns='ABCD', first_row=2, last_row=647)[source]¶
Loads spectrograph*CCD throughputs from DESI-5501 excel files.
- Parameters:
filenames – list of per-spectrograph filenames.
Returns arrays of wavelength in nm and throughput per spectrograph.
- desimodel.inputs.throughput.load_throughput(filename, specthru_row=95, thru_row=97)[source]¶
Load throughputs from DESI-0347, removing the spectrograph contributions which will be loaded separately from higher resolution data.
- Parameters:
filename – DESI-0347 Excel file location
Returns (thruspine, xlsdata), where
thruspline: InterpolatedUnivariateSpline of thru vs. wave[Angstroms] xlsdata: tuple of (wave, totalthru, specthru)
Notes
Alas, DESI-0347 doesn’t fill in the final throughput for 3500 and 9950 Angstroms, even though the inputs are there.
- desimodel.inputs.throughput.update(testdir=None, desi347_version=16, desi5501_version=3, desi5501_KOSI=True)[source]¶
Update thru-[brz].fits from DESI-0347 and DESI-0344
- Parameters:
testdir – If not None, write files here instead of standard locations under $DESIMODEL/data/
desi347_version – version of DESI-347 to use
desi5501_version – version of DESI-5501 to use
[bool] (desi5501_KOSI) – use KOSI throughput measurements in 5501
desimodel.install¶
Install data files not handled by pip install.
- desimodel.install.assert_svn_exists()[source]¶
Assert svn command exists and raise an informative error if not
- desimodel.install.default_install_dir()[source]¶
Return the default install directory. Assumes this file lives in a ‘site-packages’ directory.
- Returns:
The path to the install directory.
- Return type:
- desimodel.install.install(desimodel=None, version=None)[source]¶
Primary workhorse function.
- Parameters:
- Raises:
RuntimeError – Standard error output from svn export command when status is non-zero.
- desimodel.install.main()[source]¶
Entry point for the install_desimodel_data script.
- Returns:
An integer suitable for passing to
sys.exit()
.- Return type:
- desimodel.install.svn_export(desimodel_version=None)[source]¶
Create a svn export command suitable for downloading a particular desimodel version.
- Parameters:
desimodel_version (
str
, optional) – The version X.Y.Z to download, trunk, or something of the form branches/… Defaults to trunk.- Returns:
A svn command in list form, suitable for passing to
subprocess.Popen
.- Return type:
desimodel.io¶
I/O utility functions for files in desimodel.
- desimodel.io.datadir(surveyops=False)[source]¶
Returns location to desimodel data.
- Parameters:
surveyops (
bool
) – IfTrue
then find the relevant path for the $DESI_SURVEYOPS directory rather than the $DESIMODEL directory.
Notes
If surveyops`==``False` and
DESIMODEL
is set, then $DESIMODEL overrides data installed with the package.
- desimodel.io.findfile(filename, surveyops=False)[source]¶
Return full path to data file
$DESIMODEL/data/filename
.- Parameters:
- Returns:
The full path.
- Return type:
Notes
This is a precursor for a potential future refactor where desimodel data would be installed with the package and
DESIMODEL
would become an optional override.
- desimodel.io.get_focalplane_dates()[source]¶
Returns the dates of new focalplane definitions.
There are two levels of time-dependent changes within the focalplane. First are the focalplane definitions, defined by a set of files
$DESIMODEL/data/focalplane/{desi-exclusion,desi-focalplane,desi-state}_DATE.
. Those are the dates returned by this function, as a list of datetime objects.The second level is that, within the “state” table, there are changes to the states of individual positioners. (These are the dates returned when
get_time_range=True
is set inload_focalplane()
.)- Returns:
dates – The dates when the focalplane changed.
- Return type:
list
ofdatetime
- desimodel.io.load_desiparams()[source]¶
Returns DESI parameter dictionary loaded from
$DESIMODEL/data/desi.yaml
.- Returns:
The parameters read from the YAML file.
- Return type:
- desimodel.io.load_deviceloc()[source]¶
Returns a table from
$DESIMODEL/data/focalplane/fiberpos-all.fits
.- Returns:
The data from the FITS file, with columns converted to uppercase.
- Return type:
- desimodel.io.load_fiberpos()[source]¶
Returns fiberpos table from
$DESIMODEL/data/focalplane/fiberpos.fits
.- Returns:
The data from the FITS file, sorted by
FIBER
.- Return type:
- desimodel.io.load_focalplane(time=None, get_time_range=False)[source]¶
Load the focalplane state that is valid for the given time.
- Parameters:
time (
datetime
) – The time to query with explicit timezone. Default to current time (now()
) with timezone UTC.- Returns:
A tuple of (FP layout, exclusion polygons, state, time string). The FP layout is a Table. The exclusion polygons are a dictionary indexed by names that are referenced in the state. The state is a Table. The time string is the resulting UTC ISO format time string for the creation date of the FP model.
If get_time_range=True, returns two additional values: time_low and time_high, both datetime objects giving the range of dates over which this description of the focal plane is valid. time_high may be None, indicating that there is no later known hardware state. In particular, these dates refer to the state of the positioners, which are more fine-grained than the fp and exclusion objects.
- Return type:
- desimodel.io.load_gfa()[source]¶
Returns GFA table from
$DESIMODEL/data/focalplane/gfa.ecsv
.- Returns:
The data from the ECSV file.
- Return type:
- desimodel.io.load_pixweight(nside, pixmap=None)[source]¶
Loads
$DESIMODEL/data/footprint/desi-healpix-weights.fits
.
- desimodel.io.load_platescale()[source]¶
Loads platescale.txt.
- Returns:
The data table read from the file.
- Return type:
Notes
The returned object has these columns:
- radius
Radius from center of focal plane [mm].
- theta
Radial angle that has a centroid at this radius [deg].
- radial_platescale
Meridional (radial) plate scale [um/arcsec].
- az_platescale:
Sagittal (azimuthal) plate scale [um/arcsec].
- arclength:
Unknown description.
- desimodel.io.load_psf(channel)[source]¶
Returns specter PSF object for the given channel ‘b’, ‘r’, or ‘z’.
- Parameters:
channel ({'b', 'r', 'z'}) – Spectrograph channel.
- Returns:
A specter PSF object.
- Return type:
PSF
- desimodel.io.load_target_info()[source]¶
Loads data/targets/targets.yaml and returns the nested dictionary.
This is primarily syntactic sugar to avoid end users constructing paths and filenames by hand (which e.g. broke when targets.dat was renamed to targets.yaml).
- Returns:
The dictionary read from the YAML file.
- Return type:
- desimodel.io.load_throughput(channel)[source]¶
Returns specter Throughput object for the given channel ‘b’, ‘r’, or ‘z’.
- Parameters:
channel ({'b', 'r', 'z'}) – Spectrograph channel.
- Returns:
A specter throughput object.
- Return type:
Throughput
- desimodel.io.load_tiles(onlydesi=True, extra=False, tilesfile=None, cache=True, programs=None, surveyops=True)[source]¶
Return DESI tiles structure from
$DESI_SURVEYOPS/trunk/ops/tiles-main.ecsv
.- Parameters:
onlydesi (
bool
, optional) – IfTrue
, trim to just the tiles in the DESI footprint.extra (
bool
, optional) – IfTrue
, include extra layers withPROGRAM='EXTRA'
.tilesfile (
str
, optional) – Name of tiles file to load; or None for default. See Notes for details.cache (
bool
, optional) – IfFalse
, force reload of data from tiles file, instead of using cached values.programs (
list
or str, optional) – Pass a list of program names to restrict to only those programs, e.g. [“DARK”, “BACKUP”].surveyops (
bool
) – IfTrue
then find the relevant path for the $DESI_SURVEYOPS directory rather than the $DESIMODEL directory.
- Returns:
The data table portion of the FITS file.
- Return type:
- Raises:
FileNotFoundError – If the value of tilesfile does not exist.
Notes
Keyword-based environment variable expansion is performed on the tilesfile value, so e.g.:
tiles = load_tiles(tilesfile='{HOME}/my-tiles.fits')
will be expanded with the value of
HOME
.If the parameter tilesfile is set, this function uses the following search method:
Paths corresponding to both $DESI_SURVEYOPS/trunk/ops and $DESI_SURVEYOPS/ops are always both checked, to cover different svn checkout approaches.
If the value includes an explicit path, even
./
, use that file.If the value does not include an explicit path, and the file name is identical to a file in
$DESI_SURVEYOPS/trunk/ops/
, use the file in$DESI_SURVEYOPS/trunk/ops/
and issue a warning.If no matching file can be found at all, raise an exception.
desimodel.trim¶
Code for trimming desimodel/data into smaller files.
- desimodel.trim.inout(indir, outdir, filename)[source]¶
returns os.path.join(indir, filename) and .join(outdir, filename)
- desimodel.trim.rebin_image(image, n)[source]¶
rebin 2D array pix into bins of size n x n
New binsize must be evenly divisible into original pix image
- desimodel.trim.trim_data(indir, outdir, overwrite=False)[source]¶
Trim a
$DESIMODEL/data
directory into a lightweight version for testing.
- desimodel.trim.trim_footprint(indir, outdir)[source]¶
Copies subset of desi-tiles.fits and .ecsv but not .par. Also creates a corresponding version of desi-healpix-weights.fits.
desimodel.weather¶
Model of the expected weather conditions at KPNO during the DESI survey.
To generate a random time series of expected FWHM seeing in arcsecs and atmospheric transparency, use, for example:
n = 10000
dt = 300 # seconds
t = np.arange(n) * dt
gen = np.random.RandomState(seed=123)
seeing = sample_seeing(n, dt_sec=dt, gen=gen)
transp = sample_transp(n, dt_sec=dt, gen=gen)
The resulting arrays are randomly sampled from models of the 1D probability density and 2-point power spectral density derived from MzLS observations. See DESI-doc-3087 for details.
Used by surveysim.weather
for simulations of DESI observing and
survey strategy studies.
- desimodel.weather._seeing_fit_model(x)[source]¶
Evalute the fit to MzLS seeing described in DESI-doc-3087.
- desimodel.weather._seeing_psd(freq)[source]¶
Evaluate the ‘chi-by-eye’ fit of the seeing PSD described in DESI-doc-3087.
- desimodel.weather._transp_psd(freq)[source]¶
Evaluate the ‘chi-by-eye’ fit of the transparency PSD described in DESI-doc-3087.
- desimodel.weather.dome_closed_fractions(start_date, stop_date, replay='Y2007,Y2008,Y2009,Y2010,Y2011,Y2012,Y2013,Y2014')[source]¶
Return dome-closed fractions for each night of the survey.
Years can be replayed in any order. If the number of years to replay is less than the survey duration, they are repeated.
- Parameters:
start_date (datetime.date or None) – Survey starts on the evening of this date. Use the
first_day
config parameter if None (the default).stop_date (datetime.date or None) – Survey stops on the morning of this date. Use the
last_day
config parameter if None (the default).replay (str) – Comma-separated list of years to replay, identified by arbitrary strings that must match column names in the DESIMODEL weather history.
- Returns:
1D array of N probabilities between 0-1, where N is the number of nights spanned by the start and stop dates.
- Return type:
numpy array
- desimodel.weather.get_seeing_pdf(median_seeing=1.1, max_seeing=2.5, n=250)[source]¶
Return PDF of FWHM seeing for specified clipped median value.
Note that this is atmospheric seeing, not delivered image quality. The reference wavelength for seeing values is 6355A, in the r band, and the observed wavelength dependence in Dey & Valdes is closer to
lambda ** (-1/15)
than thelambda ** (-1/5)
predicted by Kolmogorov theory. See DESI-doc-3087 for details.Scales the clipped MzLS seeing PDF in order to achieve the requested median value. Note that clipping is applied before scaling, so the output PDF is clipped at scale * max_seeing.
- Parameters:
- Returns:
Tuple (fwhm, pdf) that tabulates pdf[fwhm]. Normalized so that
np.sum(pdf * np.gradient(fwhm)) = 1
.- Return type:
- desimodel.weather.get_transp_pdf(n=250)[source]¶
Return PDF of atmospheric transparency.
Derived from MzLS observations, but corrected for dust accumulation and measurement error. See DESI-doc-3087 for details.
- desimodel.weather.sample_seeing(n_sample, dt_sec=180.0, median_seeing=1.1, max_seeing=2.5, gen=None)[source]¶
Generate a random time series of FWHM seeing values.
See DESI-doc-3087 for details. Uses
get_seeing_pdf()
,_seeing_psd()
andsample_timeseries()
.- Parameters:
n_sample (int) – Number of equally spaced samples to generate.
dt_sec (float) – Time interval between samples in seconds.
median_seeing (float) – See
get_seeing_pdf()
.mex_seeing (float) – See
get_seeing_pdf()
.gen (np.random.RandomState or None) – Provide an existing RandomState for full control of reproducible random numbers, or None for non-reproducible random numbers.
- Returns:
1D array of randomly generated samples.
- Return type:
array
- desimodel.weather.sample_timeseries(x_grid, pdf_grid, psd, n_sample, dt_sec=180.0, gen=None)[source]¶
Sample a time series specified by a power spectrum and 1D PDF.
The PSD should describe the temporal correlations of whitened samples. Generated samples will then be unwhitened to recover the input 1D PDF. See DESI-doc-3087 for details.
Uses
whiten_transforms_from_cdf()
.- Parameters:
x_grid (array) – 1D array of N increasing grid values covering the parameter range to sample from.
pdf_grid (array) – 1D array of N increasing PDF values corresponding to each x_grid. Does not need to be normalized.
psd (callable) – Function of frequency in 1/days that returns the power-spectral density of whitened temporal fluctations to sample from. Will only be called for positive frequencies. Normalization does not matter.
n_sample (int) – Number of equally spaced samples to generate.
dt_sec (float) – Time interval between samples in seconds.
gen (np.random.RandomState or None) – Provide an existing RandomState for full control of reproducible random numbers, or None for non-reproducible random numbers.
- desimodel.weather.sample_transp(n_sample, dt_sec=180.0, gen=None)[source]¶
Generate a random time series of atmospheric transparency values.
See DESI-doc-3087 for details. Uses
get_transp_pdf()
,_transp_psd()
andsample_timeseries()
.- Parameters:
- Returns:
1D array of randomly generated samples.
- Return type:
array
- desimodel.weather.whiten_transforms(data, data_min=None, data_max=None)[source]¶
Calculate a pair of transforms to whiten and unwhiten a distribution.
Uses
desimodel.weather.whiten_transforms_from_cdf()
.- Parameters:
data (array) – 1D array of samples from the distribution to whiten.
data_min (float or None) – Clip the distribution to this minimum value, or at min(data) if None. Must be <= min(data).
data_max (float or None) – Clip the distribution to this maximum value, or at max(data) if None. Must be >= max(data).
- Returns:
- Return type:
- desimodel.weather.whiten_transforms_from_cdf(x, cdf)[source]¶
Calculate a pair of transforms to whiten and unwhiten a distribution.
The whitening transform is monotonic and invertible.
- Parameters:
x (array) – 1D array of non-decreasing values giving bin edges for the distribution to whiten and unwhiten.
cdf (array) – 1D array of non-decreasing values giving the cummulative probability density associated with each bin edge. Does not need to be normalized. Must have the same length as x.
- Returns:
Tuple (F,G) of callable objects that whiten y=F(x) and unwhiten x=G(y) samples x of the input distribution, so that y has a Gaussian distribution with zero mean and unit variance.
- Return type: