Full desisurvey API Reference

Modules

desisurvey.config

Manage survey planning and schedule configuration data.

The normal usage is:

>>> config = Configuration()
>>> config.programs.BRIGHT.max_sun_altitude()
<Quantity -13.0 deg>

Use dot notation to specify nodes in the configuration hieararchy and function call notation to access terminal node values.

Terminal node values are first converted according to YAML rules. Strings containing a number followed by valid astropy units are subsequently converted to astropy quantities. Strings of the form YYYY-MM-DD are converted to datetime.date objects.

To change a value after the configuration has been loaded into memory use, for example:

>>> config.full_moon_nights.set_value(5)

Assigned values must have the appropriate converted types, for example:

>>> import datetime
>>> config.last_day.set_value(datetime.date(2024, 1, 1))
>>> import astropy.units as u
>>> config.location.temperature.set_value(-5 * u.deg_C)

The configuration is implemented as a singleton so the YAML file is only loaded and parsed the first time a Configuration() is built. Subsequent calls to Configuration() always return the same object.

class desisurvey.config.Configuration(file_name=None)[source]

Top-level configuration data node.

_initialize(file_name=None)[source]

Initialize a configuration data structure from a YAML file.

get_path(name)[source]

Prepend this configuration’s output_path to non-absolute paths.

Configured by the output_path node and set_output_path().

An absolute path is returned immediately so an environment variable used in output_path only needs to be defined if relative paths are used.

Parameters:

name (str) – Absolute or relative path name, which does not need to exist yet.

Returns:

Path name to use. Relative path names will have our output_path prepended. Absolute path names will be unchanged.

Return type:

str

static reset()[source]

Forget our singleton instance. Mainly intended for unit tests.

set_output_path(output_path)[source]

Set the output directory for relative paths.

The path must exist when this method is called. Called by get_path() for a non-absolute path. This method updates the configuration output_path value.

Parameters:

output_path (str) – A path possibly including environment variables enclosed in {…} that will be substituted from the current environment.

Raises:

ValueError – Path uses undefined environment variable or does not exist.

class desisurvey.config.Node(value, path=[])[source]

A single node of a configuration data structure.

The purpose of this class is to allow nested dictionaries to be accessed using attribute dot notation, and to implement automatic conversion of strings of the form “<value> <units>” into corresponding astropy quantities.

property keys

Return the list of keys for a non-leaf node or raise a RuntimeError for a terminal node.

property path

Return the full path to this node using dot notation.

set_value(new_value)[source]

Set a terminal node’s value or raise a RuntimeError for a non-terminal node.

desisurvey.ephem

desisurvey.etc

desisurvey.forecast

desisurvey.holdingpen

desisurvey.NTS

desisurvey.optimize

Optimize future DESI observations.

class desisurvey.optimize.Optimizer(condition, lst_edges, lst_hist, subset=None, start=None, stop=None, init='flat', initial_ha=None, stretch=1.0, smoothing_radius=10, center=None, seed=123, weights=[5, 4, 3, 2, 1], completed=None)[source]

Initialize the hour angle assignments for specified tiles.

See DESI-3060 for details.

Parameters:
  • condition ('DARK', 'GRAY' or 'BRIGHT') – Which obsconditions to optimize.

  • lst_edges (array) – Array of N+1 LST bin edges.

  • lst_hist (array) – Array of N bins giving the available LST distribution in units of sidereal hours per bin.

  • subset (array or None) – An array of tile ID values to optimize. Optimizes all tiles with the relevant conditions if None.

  • start (date or None) – Only consider available LST starting from this date. Use the nominal survey start date if None.

  • stop (date or None) – Only consider available LST before this end date. Use the nominal survey stop date if None.

  • init ('zero', 'flat' or 'array') – Method for initializing tile hour angles: ‘zero’ sets all hour angles to zero, ‘flat’ matches the CDF of available LST to planned LST (without accounting for exposure time), ‘array’ initializes from the initial_ha argument.

  • initial_ha (array or None) – Only used when init is ‘array’. The subset arg must also be provided to specify which tile each HA applies to.

  • stretch (float) – Amount to stretch exposure times to account for factors other than dust and airmass (i.e., seeing, transparency, moon). This does not have a big effect on the results so can be approximate.

  • smoothing_radius (astropy.units.Quantity) – Gaussian sigma for calculating smoothing weights with angular units.

  • center (float or None) – Used by the ‘flat’ initialization method to specify the starting DEC for the CDF balancing algorithm. When None, the ‘flat’ method scans over a grid of center values and picks the best one, but this is relatively slow. Ignored unless init is ‘flat’.

  • seed (int or None) – Random number seed to use for stochastic elements of the optimizer. Do not use None if reproducible results are required.

  • weights (array) – Array of relative weights to use when selecting which LST bin to optimize next. Candidate bins are ordered by an estimated improvement. The length of the weights array determines how many candidates to consider, in decreasing order, and the weight values determines their relative weight. The next bin to optimize is then selected at random.

  • completed (array) – Array of tileid, donefrac_{bright/gray/dark} indicating what fraction of particular tiles has already been observed in a particular condition.

eval_RMSE(plan_hist)[source]

Evaluate the mean-squared error metric for the specified plan.

This is the metric that optimize() attempts to improve. It measures the similarity of the available and planned LST histogram shapes, but not their normalizations. A separate eval_scale() metric measures how efficiently the plan uses the available LST.

The histogram of available LST is rescaled to the same total time (area) before calculating residuals relative to the planned LST usage.

RMSE values are scaled by (10K / ntiles) so the absolute metric value is more consistent when ntiles is varied.

Parameters:

plan_hist (array) – Histogram of planned LST usage for all tiles.

Returns:

Mean squared error value.

Return type:

float

eval_loss(plan_hist)[source]

Evaluate relative loss of current plan relative to HA=0 plan.

Calculated as (T-T0)/T0 where T is the total exposure time of the current plan and T0 is the total exposure time of an HA=0 plan.

Parameters:

plan_hist (array) – Histogram of planned LST usage for all tiles.

Returns:

Loss factor.

Return type:

float

eval_scale(plan_hist)[source]

Evaluate the efficiency of the specified plan.

Calculates the minimum scale factor applied to the available LST histogram so that the planned LST usage is always <= the scaled available LST histogram. This value can be intepreted as the fraction of the available time required to complete all tiles.

This metric is only loosely correlated with the RMSE metric, so provides a useful independent check that the optimization is producing the desired results.

This metric is not well defined if any bin of the available LST histogram is empty, which indicates that some tiles will not be observable during the [start:stop] range being optimized. In this case, only bins with some available LST are included in the scale calculation.

Parameters:

plan_hist (array) – Histogram of planned LST usage for all tiles.

Returns:

Scale factor.

Return type:

float

eval_score(plan_hist)[source]

Evaluate the score that improve() tries to minimize.

Score is calculated as 100 * RMSE + 100 * loss.

Parameters:

plan_hist (array) – Histogram of planned LST usage for all tiles.

Returns:

Score value.

Return type:

float

get_exptime(ha, subset=None)[source]

Estimate exposure times for the specified tiles.

Estimates account for airmass and dust extinction only.

Parameters:
  • ha (array) – Array of hour angle assignments in degrees.

  • subset (array or None) – Restrict calculation to a subset of tiles specified by the indices in this array, or use all tiles pass to the constructor if None.

Returns:

Tuple (exptime, subset) where exptime is an array of estimated exposure times in degrees and subset is the input subset or else a slice initialized for all tiles.

Return type:

tuple

get_plan(ha, subset=None)[source]

Calculate an LST usage plan for specified hour angle assignments.

Parameters:
  • ha (array) – Array of hour angle assignments in degrees.

  • subset (array or None) – Restrict calculation to a subset of tiles specified by the indices in this array, or use all tiles pass to the constructor if None.

Returns:

Array of shape (ntiles, nbins) giving the exposure time in hours that each tile needs in each LST bin. When a subset is specified, ntiles only indexes tiles in the subset.

Return type:

array

improve(frac=1.0)[source]

Perform one iteration of improving the hour angle assignments.

Each call will adjust the HA of a single tile with a magnitude |dHA| specified by the frac parameter.

Parameters:

frac (float) – Mean fraction of an LST bin to adjust the selected tile’s HA by. Actual HA adjustments are randomly distributed around this mean to smooth out adjustments.

init_smoothing(radius)[source]

Calculate and save smoothing weights.

Weights for each pair of tiles [i,j] are calculated as:

wgt[i,j] = exp(-0.5 * (sep[i,j]/radius) ** 2)

where sep[i,j] is the separation angle between the tile centers.

Parameters:

radius (astropy.units.Quantity) – Gaussian sigma for calculating weights with angular units.

next_bin()[source]

Select which LST bin to adjust next.

The algorithm determines which bin of the planned LST usage histogram should be decreased in order to maximize the decrease of the score, assuming that the decrease is moved to one of the neighboring bins.

Since each tile’s contribution to the plan can, in general, span several LST bins and can change its area (exposure time) when its HA is adjusted, the assumptions of this algorithm are not valid in detail but it usually does a good job anyway.

This algorithm has a stochastic component controlled by the weights parameter passed to our constructor, in order to avoid getting stuck in a local minimum.

Returns:

Tuple (idx, dha_sign) where idx is the LST bin index that should be decreased (by moving one of the tiles contributing to it) and dha_sign gives the sign +/-1 of the HA adjustment required.

Return type:

tuple

plot(save=None, relative=True)[source]

Plot the current optimzation status.

Requires that matplotlib is installed.

Parameters:

save (str or None) – Filename where the generated plot will be saved.

smooth(alpha=0.1)[source]

Smooth the current HA assignments.

Each HA is replaced with a smoothed value:

(1-alpha) * HA + alpha * HA[avg]

where HA[avg] is the weighted average of all other tile HA assignments.

use_plan(save_history=True)[source]

Use the current plan and update internal arrays.

Calculates the plan_hist arrays from the per-tile plan_tiles array, and records the current values of the RMSE and scale metrics.

desisurvey.optimize.wrap(angle, offset)[source]

Wrap values in the range [0, 360] to [offset, offset+360].

desisurvey.plan

desisurvey.plots

desisurvey.rules

desisurvey.scheduler

desisurvey.svstats

desisurvey.tileqa

desisurvey.tileqa.adjacency_matrix(tilera, tiledec, fiberposfile=None)[source]

Overlap area matrix between slit blocks and radial bins, given tile ras and decs.

desisurvey.tileqa.logradecoffscheme(ras, decs, dx=0.6, ang=24, verbose=False, firstyearoptimized=True)[source]

Log spiraly ra and dec dither scheme, given a base tiling.

Dithers the base tiling by offsets in ra/cos(dec) and dec, by increasing amounts. Initial dither direction is given by ang of length dx. Subsequent dithers are rotated by 90 degrees and increased in length by a factor of exp(1/3). The fifth dither is placed at the center of the quadrilateral formed by the four previous dithers. This final set of five dithers is then duplicated, to make 10 dithers.

Parameters:
  • ras (ndarray[N]) – base tile ras

  • decs (ndarray[N]) – base tile decs

  • dx (float, degrees) – amount to dither

  • ang (float, degrees) – position angle of initial dither

  • firstyearoptimized (bool) – optimize dither order for first year

Returns:

dithered tile ras decs (ndarray[N*10]): dithered tile decs

Return type:

ras (ndarray[N*10])

desisurvey.tileqa.maketilefile(desitiles, gaiadensitymapfile, tycho2file, covfile, firstyearoptimized=True)[source]

Make tile file.

Parameters:
  • desitiles – original DESI tile file

  • gaiadensitymapfile – file name of healpix map of density of Gaia stars brighter than 19th mag.

  • tycho2file – file name of list of ra, dec, bt, vt mags of Tycho-2 stars.

  • covfile – file name of healpix coverage maps

  • firstyearoptimized – bool, use scheme optimized for early full depth coverage.

desisurvey.tileqa.match2d(x1, y1, x2, y2, rad)[source]

Find all matches between x1, y1 and x2, y2 within radius rad.

desisurvey.tileqa.match_radec(r1, d1, r2, d2, rad=0.0002777777777777778, nneighbor=0, notself=False)[source]

Match r1, d1, to r2, d2, within radius rad.

desisurvey.tileqa.qa(desitiles, nside=1024, npts=1000, compare=False, npass=5, makenew=True, oneperim=False)[source]

Make tiling QA plots; demonstrate usage.

desisurvey.tileqa.render(ra, dec, tilera, tiledec, fiberposfile=None, oneperim=False, excludebad=False)[source]

Return number of possible observations of ra, dec, given focal plane centers tilera, tiledec.

desisurvey.tileqa.simpleradecoffscheme(ras, decs, dx=0.6, ang=42)[source]

Box ra and dec scheme, given a base tiling.

Dithers the base tiling by fixed offsets in ra/cos(dec) and dec. Initial dither direction is given by ang. Dithers are dx in length, and the dither direction is rotated 90 degrees after each dither. The fifth dither is placed at the center of the square formed by the four previous dithers. This final set of five dithers is then duplicated, to make 10 dithers.

Parameters:
  • ras (ndarray[N]) – base tile ras

  • decs (ndarray[N]) – base tile decs

  • dx (float, degrees) – amount to dither

  • ang (float, degrees) – position angle of initial dither

Returns:

dithered tile ras decs (ndarray[N*10]): dithered tile decs

Return type:

ras (ndarray[N*10])

class desisurvey.tileqa.subslices(data, uind=None)[source]

Iterator for looping over subsets of an array

desisurvey.tiles

desisurvey.utils

Command-Line Scripts

afternoon_plan

collect_etc

run_plan

surveyinit

surveymovie