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.
- get_path(name)[source]
Prepend this configuration’s output_path to non-absolute paths.
Configured by the
output_pathnode andset_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.
- 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.
desisurvey.ephem
Tabulate sun and moon ephemerides during the survey.
- class desisurvey.ephem.Ephemerides(start_date, stop_date, num_obj_steps=25, restore=None)[source]
Tabulate ephemerides.
get_ephem()should normally be used rather than calling this constructor directly.- Parameters:
start_date (datetime.date) – Calculated ephemerides start on the evening of this date.
stop_date (datetime.date) – Calculated ephemerides stop on the morning of this date.
num_obj_steps (int) – Number of steps for tabulating object (ra, dec) during each 24-hour period from local noon to local noon. Ignored when restore is set.
restore (str or None) – Name of a file to restore ephemerides from. Construct ephemerides from scratch when None. A restored file must have start and stop dates that match our args.
- start
Local noon before the first night for which ephemerides are calculated.
- Type:
- stop
Local noon after the last night for which ephemerides are calculated.
- Type:
- get_available_lst(start_date=None, stop_date=None, nbins=192, origin=-60, weather=None, include_monsoon=False, include_full_moon=False, include_twilight=False)[source]
Calculate histograms of available LST for each program.
- Parameters:
start_date (date or None) – First night to include or use the first date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().stop_date (date or None) – Last night to include or use the last date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().nbins (int) – Number of LST bins to use.
origin (float) – Rotate DEC values in plots so that the left edge is at this value in degrees.
weather (array or None) – 1D array of nightly weather factors (0-1) to use, or None to calculate available LST assuming perfect weather. Length must equal the number of nights between start and stop. Values are fraction of the night with the dome open (0=never, 1=always). Use 1 -
desimodel.weather.dome_closed_fractions()to lookup suitable corrections based on historical weather data.include_monsoon (bool) – Include nights during the annual monsoon shutdowns.
include_fullmoon (bool) – Include nights during the monthly full-moon breaks.
include_twilight (bool) – Include twilight in the BRIGHT program when True.
- Returns:
Tuple (lst_hist, lst_bins) with lst_hist having shape (3,nbins) and lst_bins having shape (nbins+1,).
- Return type:
- get_moon_illuminated_fraction(mjd)[source]
Return the illuminated fraction of the moon.
Uses linear interpolation on the tabulated fractions at midnight and should be accurate to about 0.01. For reference, the fraction changes by up to 0.004 per hour.
- get_night(night, as_index=False)[source]
Return the row of ephemerides for a single night.
- Parameters:
night (date) – Converted to a date using
desisurvey.utils.get_date().as_index (bool) – Return the row index of the specified night in our per-night table if True. Otherwise return the row itself.
- Returns:
Row of ephemeris data for the requested night or the index of this row (selected via
as_index).- Return type:
- get_night_program(night, include_twilight=False, program_as_int=False)[source]
Return the program sequence for one night.
The program definitions are taken from
desisurvey.config.Configurationand depend only on sun and moon ephemerides for the night.- Parameters:
night (date) – Converted to a date using
desisurvey.utils.get_date().include_twilight (bool) – Include twilight time at the start and end of each night in the BRIGHT program.
program_as_int (bool) – Return program encoded as a small integer instead of a string when True.
- Returns:
Tuple (programs, changes) where programs is a list of N program names and changes is a 1D numpy array of N+1 MJD values that bracket each program during the night.
- Return type:
- get_program_hours(start_date=None, stop_date=None, include_monsoon=False, include_full_moon=False, include_twilight=True)[source]
Tabulate hours in each program during each night of the survey.
Use
desisurvey.plots.plot_program()to visualize program hours.This method calculates scheduled hours with no correction for weather. Use 1 -
desimodel.weather.dome_closed_fractions()to lookup nightly corrections based on historical weather data.- Parameters:
ephem (
desisurvey.ephem.Ephemerides) – Tabulated ephemerides data to use for determining the program.start_date (date or None) – First night to include or use the first date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().stop_date (date or None) – Last night to include or use the last date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().include_monsoon (bool) – Include nights during the annual monsoon shutdowns.
include_fullmoon (bool) – Include nights during the monthly full-moon breaks.
include_twilight (bool) – Include twilight time at the start and end of each night in the BRIGHT program.
- Returns:
Numpy array of shape (3, num_nights) containing the number of hours in each program (0=DARK, 1=GRAY, 2=BRIGHT) during each night.
- Return type:
array
- get_row(row_index)[source]
Return the specified row of our table.
- Parameters:
row_index (int) – Index starting from zero of the requested row. Negative values are allowed and specify offsets from the end of the table in the usual way.
Returns
int (astropy.table.Row or) – Row of ephemeris data for the requested night.
- is_full_moon(night, num_nights=None)[source]
Test if a night occurs during a full-moon break.
The full moon break is defined as the
num_nightsnights where the moon is most fully illuminated at local midnight. This method should normally be called withnum_nightsequal to None, in which case the value is taken from ourdesisurvey.config.Configuration`.- Parameters:
night (date) – Converted to a date using
desisurvey.utils.get_date().num_nights (int or None) – Number of nights to block out around each full-moon.
- Returns:
True if the specified night falls during a full-moon break.
- Return type:
- property table
Read-only access to our internal table.
- tabulate_program(mjd, include_twilight=False, as_tuple=True)[source]
Tabulate the program during one night.
The program definitions are taken from
desisurvey.config.Configurationand depend only on sun and moon ephemerides for the night.- Parameters:
- Returns:
Tuple (dark, gray, bright) of boolean arrays that tabulates the program at each input MJD or an array of small integer indices into
desisurvey.tiles.Tiles.CONDITIONS, with the special value -1 indicating DAYTIME. All output arrays have the same shape as the inputmjdarray.- Return type:
tuple or array
- desisurvey.ephem.get_ephem(use_cache=True, write_cache=True)[source]
Return tabulated ephemerides for (START_DATE,STOP_DATE).
The pyephem module must be installed to calculate ephemerides, but is not necessary when a FITS file of precalcuated data is available.
- Parameters:
use_cache (bool) – Use cached ephemerides from memory or disk if possible when True. Otherwise, always calculate from scratch.
write_cache (bool) – When True, write a generated table so it is available for future invocations. Writing only takes place when a cached object is not available or
use_cacheis False.
- Returns:
Object with tabulated ephemerides for (START_DATE,STOP_DATE).
- Return type:
- desisurvey.ephem.get_grid(step_size=1, night_start=-6, night_stop=7)[source]
Calculate a grid of equally spaced times covering one night.
In case the requested step size does not evenly divide the requested range, the last grid point will be rounded up.
The default range covers all possible observing times at KPNO.
- Parameters:
step_size (
astropy.units.Quantity, optional) – Size of each grid step with time units, default 1 min.night_start (
astropy.units.Quantity, optional) – First grid point relative to local midnight with time units, default -6 h.night_stop (
astropy.units.Quantity, optional) – Last grid point relative to local midnight with time units, default 7 h.
- Returns:
Numpy array of dimensionless offsets relative to local midnight in units of days.
- Return type:
array
- desisurvey.ephem.get_object_interpolator(row, object_name, altaz=False)[source]
Build an interpolator for object location during one night.
Wrap around in RA is handled correctly and we assume that the object never wraps around in DEC. The interpolated unit vectors should be within 0.3 degrees of the true unit vectors in both (dec,ra) and (alt,az).
- Parameters:
row (astropy.table.Row) – A single row from the ephemerides astropy Table corresponding to the night in question.
object_name (string) – Name of the object to build an interpolator for. Must be listed under avoid_objects in
our configuration.altaz (bool) – Interpolate in (alt,az) if True, else interpolate in (dec,ra).
- Returns:
A callable object that takes a single MJD value or an array of MJD values and returns the corresponding (dec,ra) or (alt,az) values in degrees, with -90 <= dec,alt <= +90 and 0 <= ra,az < 360.
- Return type:
callable
desisurvey.etc
Calculate the nominal exposure time for specified observing conditions.
Use exposure_time() to combine all effects into an exposure time in
seconds, or call functions to calculate the individual exposure-time factors
associated with each effect.
The following effects are included: seeing, transparency, galactic dust extinction, airmass, scattered moonlight. The following effects are not yet implemented: twilight sky brightness, clouds, variable OH sky brightness.
- class desisurvey.etc.ExposureTimeCalculator(save_history=False)[source]
Online Exposure Time Calculator.
Track observing conditions (seeing, transparency, sky background) during an exposure using the
start(),update()andstop()methods.- Exposure time tracking is configured by the following parameters:
nominal_exposure_time
new_field_setup
same_field_setup
cosmic_ray_split
min_exposures
Note that this version applies an average correction for the moon during the GRAY and BRIGHT programs, rather than idividual corrections based on the moon parameters. This will be fixed in a future version.
- Parameters:
save_history (bool) – When True, records the history of internal calculations during an exposure, for debugging and plotting.
- could_complete(t_remaining, program, snr2frac, exposure_factor)[source]
Determine which tiles could be completed.
Completion refers to achieving SNR2 = 1, which might require multiple exposures.
Used by
desisurvey.scheduler.Scheduler.next_tile()and usesestimate_exposure().- Parameters:
t_remaining (float) – Time remaining in units of days.
program (str) – Program that the candidate tiles belong to (must be the same for all tiles).
snr2frac (float or array) – Fractional SNR2 integrated so far for each tile to consider.
exposure_factor (float or array) – Exposure-time factor for each tile to consider.
- Returns:
1D array of booleans indicating which tiles (if any) could completed within the remaining time.
- Return type:
array
- estimate_exposure(program, snr2frac, exposure_factor, nexp_completed=0)[source]
Estimate exposure time(s).
Can be used to estimate exposures for one or many tiles from the same program.
- Parameters:
program (str) – Name of the program to estimate exposure times for. Used to determine the nominal exposure time. All tiles must be from the same program.
snr2frac (float or array) – Fractional SNR2 integrated so far for the tile(s) to estimate.
exposure_factor (float or array) – Exposure-time factor for the tile(s) to estimate.
nexp_completed (int or array) – Number of exposures completed so far for tile(s) to estimate.
- Returns:
Tuple (texp_total, texp_remaining, nexp) of floats or arrays, where texp_total is the total time that would be required under current conditions, texp_remaining is the remaining time under current conditions taking the already accumulated SNR2 into account, and nexp is the estimated number of remaining exposures required.
- Return type:
- property snr2frac
Integrated fractional SNR2 of tile currently being exposed.
Includes signal accumulated in previous exposures. Initialized by
start(), updated byupdate()and frozen bystop().
- start(mjd_now, tileid, program, snr2frac, exposure_factor, seeing, transp, sky)[source]
Start tracking an exposure.
Must be called before using
update()to track changing conditions during the exposure.- Parameters:
mjd_now (float) – MJD timestamp when exposure starts.
tileid (int) – ID of the tile being exposed. This is only used to recognize consecutive exposures of the same tile.
program (str) – Name of the program the exposed tile belongs to.
snr2frac (float) – Previous accumulated fractional SNR2 of the exposed tile.
exposure_factor (float) – Exposure factor of the tile when the exposure starts, based on the current conditions specified by the remaining parameters.
seeing (float) – Initial atmospheric seeing in arcseconds.
transp (float) – Initial atmospheric transparency (0,1).
sky (float) – Initial sky background level.
- stop(mjd_now)[source]
Stop tracking an exposure.
After calling this method, use
exptimeto look up the exposure time.- Parameters:
mjd_now (float) – MJD timestamp when the current exposure was stopped.
- Returns:
True if this tile is “done” or False if another exposure of the same tile should be started immediately. Note that “done” normally means the tile has reached its target SNR2, but could also mean that the SNR2 accumulation rate has fallen below some threshold so that it is no longer useful to continue exposing.
- Return type:
- update(mjd_now, seeing, transp, sky)[source]
Track changing conditions during an exposure.
Must call
start()first to start tracking an exposure.- Parameters:
mjd_now (float) – Current MJD timestamp.
seeing (float) – Estimate of average atmospheric seeing in arcseconds since last update (or start).
transp (float) – Estimate of average atmospheric transparency since last update (or start).
sky (float) – Estimate of average sky background level since last update (or start).
- Returns:
True if the exposure should continue integrating.
- Return type:
- desisurvey.etc.airmass_exposure_factor(airmass)[source]
Scaling of exposure time with airmass relative to nominal.
The exponent 1.25 is based on empirical fits to BOSS exposure times. See eqn (6) of Dawson 2012 for details.
- desisurvey.etc.dust_exposure_factor(EBV)[source]
Scaling of exposure time with median E(B-V) relative to nominal.
The model uses the SDSS-g extinction coefficient (3.303) from Table 6 of Schlafly & Finkbeiner 2011 by default, or config.ebv_coefficient if specified.
- desisurvey.etc.exposure_time(program, seeing, transparency, airmass, EBV, moon_frac, moon_sep, moon_alt)[source]
Calculate the total exposure time for specified observing conditions.
The exposure time is calculated as the time required under nominal conditions multiplied by factors to correct for actual vs nominal conditions for seeing, transparency, dust extinction, airmass, and scattered moon brightness.
Note that this function returns the total exposure time required to achieve the target SNR**2 at current conditions. The caller is responsible for adjusting this value when some signal has already been acummulated with previous exposures of a tile.
- Parameters:
program ('DARK', 'BRIGHT' or 'GRAY') – Which program to use when setting the target SNR**2.
seeing (float or array) – FWHM seeing value(s) in arcseconds.
transparency (float or array) – Dimensionless transparency value(s) in the range [0-1].
EBV (float or array) – Median dust extinction value(s) E(B-V) for the tile area.
airmass (float) – Airmass used for observing this tile.
moon_frac (float) – Illuminated fraction of the moon, between 0-1.
moon_sep (float) – Separation angle between field center and moon in degrees.
moon_alt (float) – Altitude angle of the moon above the horizon in degrees.
- Returns:
Estimated exposure time(s) with time units.
- Return type:
astropy.unit.Quantity
- desisurvey.etc.moon_exposure_factor(moon_frac, moon_sep, moon_alt, airmass)[source]
Calculate exposure time factor due to scattered moonlight.
The returned factor is relative to dark conditions when the moon is below the local horizon.
This factor is based on a study of SNR for ELG targets and designed to achieve a median SNR of 7 for a typical ELG [OII] doublet at the lower flux limit of 8e-17 erg/(cm2 s A), averaged over the expected ELG target redshift distribution 0.6 < z < 1.7.
TODO: - Check the assumption that exposure time scales with SNR ** -0.5. - Check if this ELG-based analysis is also valid for BGS targets.
For details, see the jupyter notebook doc/nb/ScatteredMoon.ipynb in this package.
- Parameters:
moon_frac (float) – Illuminated fraction of the moon, in the range [0,1].
moon_sep (float) – Separation angle between field center and moon in degrees, in the range [0,180].
moon_alt (float) – Altitude angle of the moon above the horizon in degrees, in the range [-90,90].
airmass (float) – Airmass used for observing this tile, must be >= 1.
- Returns:
Dimensionless factor that exposure time should be increased to account for increased sky brightness due to scattered moonlight. Will be 1 when the moon is below the horizon.
- Return type:
- desisurvey.etc.seeing_exposure_factor(seeing, sbprof='ELG')[source]
Scaling of exposure time with seeing, relative to nominal seeing. The model is based on DESI simulations with convolutions of realistic atmospheric and instrument PSFs, for a nominal sample of DESI ELG targets (including redshift evolution of ELG angular size).
The simulations predict SNR for the ELG [OII] doublet during dark-sky conditions at airmass X=1. The exposure factor assumes exposure time scales with SNR ** -0.5.
desisurvey.forecast
Simple forecast of survey progress and margin.
- class desisurvey.forecast.Forecast(start_date=None, stop_date=None, use_twilight=False, weather=None, design_hourangle=None)[source]
Compute a simple forecast of survey progress and margin.
Based on config, ephemerides, tiles.
- Parameters:
start_date (datetime.date) – Forecast for survey that starts on the evening of this date.
stop_date (datetime.date) – Forecast for survey that stops on the morning of this date.
use_twilight (bool) – Include twilight time in the forecast scheduled time?
weather (array or None) – 1D array of nightly weather factors (0-1) to use, or None to use
desisurvey.plan.load_weather(). The array length must equal the number of nights in [start,stop). Values are fraction of the night with the dome open (0=never, 1=always). Use 1 -desimodel.weather.dome_closed_fractions()to lookup suitable corrections based on historical weather data.design_hourangle (array or None) – 1D array of design hour angles to use in degrees, or None to use
desisurvey.plan.load_design_hourangle().
desisurvey.holdingpen
- desisurvey.holdingpen.missing_tileid(fadir, faholddir)[source]
Return missing TILEID and superfluous TILEID.
The fiberassign holding pen should include all TILEID for available, unobserved tiles. It should include no TILEID for unavailable or observed tiles. This function computes the list of TILEID that should exist, but do not, as well as the list of TILEID that should not exist, but do.
- Parameters:
- Returns:
missingtiles, extratiles
missingtiles (array) – array of TILEID for tiles that do not exist, but should. These need to be designed and added to the holding pen.
extratiles (array) – array of TILEID for tiles that exist, but should not. These need to be deleted from the holding pen.
- desisurvey.holdingpen.tileid_to_clean(faholddir, fadir, mtldone)[source]
Identify invalidated fiberassign files for deletion.
Scans faholddir for fiberassign files. Compares the MTLTIMES with the times in the mtldone file. If a fiberassign file was designed before an overlapping tile which later had MTL updates, that fiberassign file is “invalid” and should be deleted.
desisurvey.NTS
Next Tile Selector
Based on our google sheet () these are the expected inputs:
skylevel: current sky level [counts s-1 cm-2 arcsec-2] (from ETC, at the end of last exposure)
seeing: current atmospheric seeing PSF FWHM [arcsec] (from ETC, at the end of last exposure)
transparency: current atmospheric transparency [0-1, where 0=total cloud cover] (from ETC, at the end of last exposure)
obsplan: filename containing that nights observing plan
program (optional): request a tile will be in that program,
otherwise get next field chooses program based on current conditions
previoustiles (optional): list of tiles that have been observed that night
These variables are in the:
RA _prior: in degrees, used only for user over-ride, defaults to -99
DEC_prior: in degrees, used only for user over-ride, defaults to -99
EFS: for slewing minimization; not used.
If input values are missing (e.g. first exposure of the night), the NTS falls back to reasonable defaults for skylevel etc.
- The primary output of the NTS will be a dictionary with the name of the fiber assign file (full path)
The naming convention is fiberassign_<tileid>.fits
In addition, the following keys/information is returned by the NTS:
tileid: (int) DESI Tile ID
s2n: (foat) Requested signal to noice (for ETC)
foundtile (boolean): indicates whether field selector was successful.
exptime: expected exposure time based on ETC information from previous exposure [seconds]
maxtime: maximum allowable exposure time [seconds]
Names are converted to FITS convention: TILEID, S2NREQ, EXTTIME, MAXTIME, FBRASSGN
- class desisurvey.NTS.QueuedList(fn)[source]
Simple class to manage list of exposures already observed in a night.
- Parameters:
fn (str) – file name where QueuedList is backed to disk.
- class desisurvey.NTS.RequestLog(fn)[source]
Simple class to log requests to NTS.
- Parameters:
fn (str) – file name where RequestLog is stored.
- desisurvey.NTS.azinrange(az, low, high)[source]
Return whether azimuth is between low and high, trying to respect the 360 deg boundary.
We transform high so that it is in the range [low, low+360]. We then transform az likewise, so that the test can be done as low <= az <= high. In this scheme, azinrange(0, 2, 1) = True, since low, high = [2, 1] is interpreted as all angles between 2 and 361 degrees.
- Parameters:
az (azimuth (deg))
low (lower bound on azimuth (deg))
high (upper bound on azimuth (deg))
- Return type:
Array of same shape as az, indicating if az is between low and high.
- desisurvey.NTS.move_tile_into_place(tileid, speculative=False)[source]
Move fiberassign file into place if not already there.
Observed fiberassign files are kept in DOS_DESI_TILES/FIBER_ASSIGN_DIR, while unobserved ones are kept in FA_HOLDING_PEN. This routine checks if a given TILEID is already available in the primary location, and otherwise copies it into place from the holding pen.
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 separateeval_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:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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.
desisurvey.plan
Plan future DESI observations.
- class desisurvey.plan.Planner(rules=None, restore=None, simulate=False, log=None)[source]
Coordinate afternoon planning activities.
- Parameters:
rules (object or None) – Object with an
applymethod that is used to implement survey strategy by updating tile priorities each afternoon. When None, all tiles have equal priority.restore (str or None) – Restore internal state from the snapshot saved to this filename, or initialize a new planner when None. Use
save()to save a snapshot to be restored later. Filename is relative to the configured output path unless an absolute path is provided. Raise a RuntimeError if the saved tile IDs do not match the current tiles_file values.simulate (bool) – If True, simulate fiber assignment process.
log (log object or None) – logging object to use; None for desiutil default.
- add_pending_tile(tileid)[source]
Add a newly observed, now-pending tile to the pending tile list.
Updates tile availability so that this tile’s neighbors will not be observed until this tile is completed.
- Parameters:
tileid (int)
- afternoon_plan(night)[source]
Update plan for a given night. Update tile availability and priority.
- Parameters:
night (str) – night string, YYYY-MM-DD, to be planned. This argument has no effect for when Plan.simulate = False; in this case, tile availability and priority is based entirely on what files are currently present in the fiberassign directory and what the planner believes the current tile completions are.
- Returns:
boolean arrays indicating newly observed and newly completed tiles.
- Return type:
new_observed (array), new_completed (array)
- fiberassign(dirnames)[source]
Update list of tiles available for spectroscopy.
Scans given directory looking for fiberassign file and populates Plan object accordingly.
- Parameters:
dirnames (list) – list of directory names where fiberassign files are to be found This directory is recursively scanned for all files with names matching tile-(d+).fits. TILEIDs are populated according to the name of the fiberassign file, and any header information is ignored.
- prefer_low_passnum()[source]
Mark only tiles available that are in the lowest pass of any overlapping tiles.
- save(name)[source]
Save a snapshot of our current state that can be restored.
The output file has a binary table (extname PLAN) with columns TILEID, CENTERID, PASS, RA, DEC, PROGRAM, IN_DESI, EBV_MED, DESIGNHA, PRIORITY, STATUS, and DONEFRAC. Simulations also include COUNTDOWN and header keywords CADENCE, FIRST, LAST.
- Parameters:
name (str) – Name of FITS file where the snapshot will be saved. The file will be saved under our configuration’s output path unless name is already an absolute path. Pass the same name to the constructor’s
restoreargument to restore this snapshot.
- set_donefrac(tileid, donefrac=None, status=None, ignore_pending=False, nobs=None)[source]
Update planner with new tile donefrac.
- Parameters:
tileid (array) – 1D array of integer tileIDs to update
donefrac (array) – 1D array of completion fractions for tiles, matching tileid, optional
status (array) – 1D array of tile status to update; optional
ignore_pending (bool) – do not mark newly started files as pending
nobs (array) – 1D array of number of observations of each tile A tile with at least 1 observation will never be considered unobserved, regardless of whether it has zero donefrac.
- desisurvey.plan.load_design_hourangle()[source]
Load design hour-angle assignments from disk.
If hour angles are present in the tile file, defaults to those. Otherwise reads column ‘DESIGNHA’ from file saved by the
surveyinitscript. Contents must row-match the tile file.- Parameters:
name (str) – Name of the ecsv file to read. A relative path is assumed to refer to the output path specified in the configuration.
- Returns:
1D array of design hour angles in degrees, with indexing that matches
desisurvey.tiles.Tiles.- Return type:
array
- desisurvey.plan.load_weather(start_date=None, stop_date=None, name='surveyinit.fits')[source]
Load dome-open fraction expected during each night of the survey.
Reads Image HDU ‘WEATHER’. This is the format saved by the
surveyinitscript, but any FITS file following the same convention can be used.- Parameters:
name (str) – Name of the FITS file to read. A relative path is assumed to refer to the output path specified in the configuration.
start_date (date or None) – First night to include or use the first date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().stop_date (date or None) – First night to include or use the last date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().
- Returns:
1D array of length equal to the span between stop_date and start_date. Values are between 0 (dome closed all night) and 1 (dome open all night).
- Return type:
array
desisurvey.plots
Utility functions for plotting DESI survey progress and planning.
- desisurvey.plots.plot_monthly(p, program='DARK', monsoon=False, fullmoon=True, cmap='viridis', save=None)[source]
Plot average nightly visibility by month.
- Parameters:
p (desisurvey.old.schedule.Scheduler) – The scheduler object to use.
program ('DARK', 'GRAY', 'BRIGHT' or 'ANY') – Name of the program to display visibility for.
monsoon (bool) – Do not observe during scheduled monsoon shutdowns? Ignored if
whenspecifies a time.fullmoon (bool) – Do not observe during scheduled full-moon breaks? Ignored if
whenspecifies a time.cmap (matplotlib colormap spec) – Colormap to use to represent observing efficiency. Not used for a time series plot.
save (string or None) – Name of file where plot should be saved. Format is inferred from the extension.
- Returns:
tuple – Tuple (figure, axes) returned by
plt.subplots().Visibility does not include dust extinction or monthly weather factors.
The nightly moon is displayed except for the DARK program, with an area
proportional to the illuminated fraction and the nightly program time.
Requires that the matplotlib and basemap packages are installed.
- desisurvey.plots.plot_next_field(date_string, obs_num, ephem, window_size=7.0, max_airmass=2.0, min_moon_sep=50.0, max_bin_area=1.0, save=None)[source]
Plot diagnostics for the next field selector.
The matplotlib and basemap packages must be installed to use this function.
- Parameters:
date_string (string) – Observation date of the form ‘YYYYMMDD’.
obs_num (int) – Observation number on the specified night, counting from zero.
ephem (
desisurvey.ephem.Ephemerides) – Ephemerides covering this night.
- desisurvey.plots.plot_observed(progress, include='observed', start_date=None, stop_date=None, what='exptime', print_summary=False, save=None)[source]
Plot a summary of observed tiles.
Reports progress tracked by
desisurvey.progress.Progress.usingplot_sky_passes()to display a summary of observed tiles in each pass.- Parameters:
progress (desisurvey.progress.Progress) – Progress tracker to use.
include ('all', 'observed', or 'completed') – Specify which tiles to include in the summary. The ‘observed’ selection will include tiles that have been observed at least once but have not yet reached their SNR**2 goal.
start_date (date or None) – Plot observations starting on the night of this date, or starting with the first observation if None. Must be convertible to a date using
desisurvey.utils.get_date().stop_date (date or None) – Plot observations ending on the morning of this date, or ending with the last observation if None. Must be convertible to a date using
desisurvey.utils.get_date().what (string) – What quantity to plot for each planned tile. Must be a column name in the summary table returned by
desisurvey.progress.Progress.get_summary().print_summary (bool) – Print a summary of observed tiles.
save (string or None) – Name of file where plot should be saved.
- Returns:
Tuple (figure, axes) returned by
plt.subplots().- Return type:
- desisurvey.plots.plot_program(ephem, start_date=None, stop_date=None, style='localtime', include_monsoon=False, include_full_moon=False, include_twilight=True, night_start=-6.5, night_stop=7.5, num_points=500, bg_color='lightblue', save=None)[source]
Plot an overview of the DARK/GRAY/BRIGHT program.
Uses
desisurvey.ephem.get_program_hours()to calculate the hours available for each program during each night.The matplotlib and basemap packages must be installed to use this function.
- Parameters:
ephem (
desisurvey.ephem.Ephemerides) – Tabulated ephemerides data to use for determining the program.start_date (date or None) – First night to include in the plot or use the first date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().stop_date (date or None) – First night to include in the plot or use the last date of the survey. Must be convertible to a date using
desisurvey.utils.get_date().style (string) – Plot style to use for the vertical axis: “localtime” shows time relative to local midnight, “histogram” shows elapsed time for each program during each night, and “cumulative” shows the cummulative time for each program since
start_date.include_monsoon (bool) – Include nights during the annual monsoon shutdowns.
include_fullmoon (bool) – Include nights during the monthly full-moon breaks.
include_twilight (bool) – Include twilight time at the start and end of each night in the BRIGHT program.
night_start (float) – Start of night in hours relative to local midnight used to set y-axis minimum for ‘localtime’ style and tabulate nightly program.
night_stop (float) – End of night in hours relative to local midnight used to set y-axis maximum for ‘localtime’ style and tabulate nightly program.
num_points (int) – Number of subdivisions of the vertical axis to use for tabulating the program during each night. The resulting resolution will be
(night_stop - night_start) / num_pointshours.bg_color (matplotlib color) – Axis background color to use. Must be a valid matplotlib color.
save (string or None) – Name of file where plot should be saved. Format is inferred from the extension.
- Returns:
Tuple (figure, axes) returned by
plt.subplots().- Return type:
- desisurvey.plots.plot_scheduler(s, start_date=None, stop_date=None, where=None, when=None, night_summary='dark', dust=True, monsoon=True, fullmoon=True, weather=False, cmap='magma', save=None)[source]
Plot a summary of the scheduler observing efficiency forecast.
Requires that the matplotlib and basemap packages are installed.
- Parameters:
s (desisurvey.old.schedule.Scheduler) – The scheduler object to use.
start_date (date or None) – First night to include in the plot or use the first scheduler date. Must be convertible to a date using
desisurvey.utils.get_date(). Ignored ifwhenspecifies a time.stop_date (date or None) – First night to include in the plot or use the last scheduler date. Must be convertible to a date using
desisurvey.utils.get_date(). Ignored ifwhenspecifies a time.where (int, 'best', 'random', iterable or None) – Plot a time series of observing efficiency each night for a specified tile ID, the best location or averaging over randomly chosen locations. An iterable of int, ‘best’, ‘random’ is also allowed. Cannot be combined with the
whenoption.when (astropy.time.Time, int, 'best', 'random' or None) – Plot an all-sky map of observing efficiency for a specified time, each location’s best night or else averaging over randomly chosen nights. A time can be specified with a timestamp or a temporal index. Cannot be combined with the
whereoption.night_summary ('best', '24hr' or 'dark') – Summarize the observing efficiency during each night picking either the best time slot, or else averaging over 24 hours or the actual length of the night. Ignored if
whenspecifies a time.dust (bool) – Should dust extinction be included in the observing efficiency?
monsoon (bool) – Do not observe during scheduled monsoon shutdowns? Ignored if
whenspecifies a time.fullmoon (bool) – Do not observe during scheduled full-moon breaks? Ignored if
whenspecifies a time.weather (bool) – Reweight exposure factors by expected dome-open fraction each month. Ignored if
whenspecifies a time.cmap (matplotlib colormap spec) – Colormap to use to represent observing efficiency. Not used for a time series plot.
save (string or None) – Name of file where plot should be saved. Format is inferred from the extension.
- Returns:
Tuple (figure, axes) returned by
plt.subplots().- Return type:
- desisurvey.plots.plot_sky_passes(ra, dec, passnum, z, clip_lo=None, clip_hi=None, label='label', cmap='viridis', save=None)[source]
Plot sky maps for each pass of a per-tile scalar quantity.
The matplotlib and basemap packages must be installed to use this function.
- Parameters:
ra (array) – Array of RA values to use in degrees.
dec (array) – Array of DEC values to use in degrees.
pass (array) – Array of integer pass values to use.
z (array) – Array of per-tile values to plot.
clip_lo (float or string or None) – See
desiutil.plot.prepare_data()clip_hi (float or string or None) – See
desiutil.plot.prepare_data()label (string) – Brief description of per-tile value
zto use for axis labels.cmap (colormap name or object) – Matplotlib colormap to use for mapping data values to colors.
save (string or None) – Name of file where plot should be saved. Format is inferred from the extension.
- Returns:
Tuple (figure, axes) returned by
plt.subplots().- Return type:
desisurvey.rules
Manage and apply tile observing priorities using rules.
- class desisurvey.rules.Rules(file_name='rules.yaml')[source]
Load rules from the specified file.
Read tile group definitions and observing rules from the specified YAML file.
- Parameters:
file_name (str) – Name of YAML file containing the rules to use. A relative path refers to our configured output path.
desisurvey.scheduler
Schedule observations during an observing night.
This module supercedes desisurvey.old.schedule.
- class desisurvey.scheduler.Scheduler(plan, log=None)[source]
Create a new next-tile scheduler.
Design hour angles are read from the output of
surveyinitusingdesisurvey.plan.load_design_hourangle(), by default.The only internal state needed by the scheduler is the list of accumulated SNR2 fractions per tile, which can be restored from a file created using
save().A newly created or restored scheduler must be configured with
init_night()(to precompute data for a night’s observing) before tiles can be selected.Use
next_tile()to select the next tile to observe during a night. If the tile is observed, the internal state must be updated with a call toupdate_snr().- Parameters:
plan (desisurvey.plan.Plan instance to use for planning)
log (log object to use)
- current_conditions(mjd_now, ETC, verbose=False, seeing=None, transparency=None, skylevel=None, airmass=None, speed=None)[source]
Return current conditions, based on ephemerides or speed.
- init_night(night, use_twilight=False)[source]
Initialize scheduling for the specified night.
Must be called before calls to
next_tile().The pool of available tiles during the night consists of those that:
Have fibers assigned.
Have non-zero priority (aka “planned”).
Have not already reached their target SNR (aka “completed”).
Are not too close to a planet during this night.
Tile priority is assumed fixed during the night. When the moon is up, tiles are also vetoed if they are too close to the moon. The angles that define “too close” to a planet or the moon are specified in config.avoid_bodies.
- next_tile(mjd_now, ETC, seeing, transp, skylevel, HA_sigma=15.0, greediness=0.0, program=None, verbose=False, current_ra=None, current_dec=None, speed=None)[source]
Select the next tile to observe.
The
init_night()method must be called before calling this method during a night.The (log) score for each observable tile is calculated as:
\[-(1 - g)\,\frac{1}{2} \left( \frac{\text{HA} - \text{HA}_0}{\sigma_{\text{HA}}} \right)^2 - g \log \frac{t_\text{exp}}{t_\text{nom}} + \log P\]where \(\text{HA}\) and \(\text{HA}_0\) are the current and design hour angles, respectively, \(g\) is the
greedinessparameter below, and \(P\) are the tile priorities used to implement survey strategy.- Parameters:
mjd_now (float) – Time when the decision is being made.
ETC (
desisurvey.etc.ExposureTimeCalculator) – Object with methodscould_complete()andweather_factor(). Normally an instance ofdesisurvey.etc.ExposureTimeCalculator.seeing (float) – Estimate of current atmospherid seeing in arcseconds.
transp (float) – Estimate of current atmospheric transparency in the range 0-1.
HA_sigma (float) – RMS in degrees for the Gaussian penalty applied to tiles observed away from their design hour angle.
greediness (float) – Parameter that controls the balance between observing at the design hour angle and observing tiles with the small exposure-time factor. Set this value to zero to only consider hour angle or to one to only consider isntantaneous efficiency. The meaning of intermediate values will depend on the value of
HA_sigmaand how exposure factors are calculated. Refer to the equation above for details. Must be between 0 and 1.program (string) – PROGRAM of tile to select. Default of None selects the appropriate PROGRAM given current moon/twilight conditions. Forcing a particular program leads PROGEND to be infinity.
current_ra (float) – current ra of telescope; used for computing penalties to long slews
current_dec (float) – current dec of telescope; used for computing penalties to long slews
speed (dict) – dictionary of DARK, BRIGHT, BACKUP, giving current estimated survey speeds in each program. If present, used instead of transp/skylevel/seeing to estimate exposure times and pick programs.
- Returns:
Tuple (TILEID,PROGRAM,DONEFRAC,EXPFAC,AIRMASS,PROGRAM,PROGEND) giving the ID and associated properties of the selected tile. When no tile is observable, only the last two tuple fields will be valid, and this method should be called again after some dead-time delay. The tuple fields are:
TILEID: ID of the tile to observe.
PROGRAM: program of the tile to observe.
DONEFRAC: fractional SNR2 already accumulated for the selected tile.
EXPFAC: initial exposure-time factor for the selected tile.
AIRMASS: initial airmass of the selected tile.
SCHEDPROGRAM: scheduled program at
mjd_now, which might be different from the program of the selected (TILEID, PASSNUM).PROGEND: MJD timestamp when the scheduled program ends.
- Return type:
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:
- 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.
desisurvey.tiles
Manage static information associated with tiles, programs and passes.
Each tile has an assigned program name. The program names (DARK, BRIGHT) are predefined in terms of conditions on the ephemerides, but not all programs need to be present in a tiles file. Pass numbers are arbitrary integers and do not need to be consecutive or dense.
To ensure consistent and efficient usage of static tile info, all code should use:
tiles = desisurvey.tiles.get_tiles()
To use a non-standard tiles file, change the configuration before the
first call to get_tiles() with:
config = desisurvey.config.Configuration()
config.tiles_file.set_value(name)
The Tiles class returned by get_tiles() is a wrapper around
the FITS table contained in a tiles file, that adds some precomputed derived
attributes for consistency and efficiency.
- class desisurvey.tiles.Tiles(tiles_file=None)[source]
Manage static info associated with the tiles file.
- Parameters:
tile_file (str or None) – Name of the tiles file to use or None for the default specified in our configuration.
- _calculate_neighbors()[source]
Initialize attribute _neighbors. A neigbor is defined as a tile in the same pass within 3 * config.tile_radius if config.tiles_lowpass is True. Otherwise, it’s all tiles within the program within 3 * config.tile_radius.
This is relatively slow, so only used the first time
overlappingproperties are accessed.
- _calculate_overlaps()[source]
Initialize attributes _overlapping.
Uses the config parameters
fiber_assignment_delayandtile_diameterto determine overlap dependencies.This is relatively slow, so only used the first time
overlappingproperties are accessed.
- airmass(hour_angle, mask=None)[source]
Calculate tile airmass given hour angle.
- Parameters:
hour_angle (array) – Array of hour angles in degrees to use. If mask is None, then should have length
self.ntiles. Otherwise, should have a value per non-zero entry in the mask.mask (array or None) – Boolean mask of which tiles to perform the calculation for.
- Returns:
Array of airmasses corresponding to each input hour angle.
- Return type:
array
- airmass_at_mjd(mjd, mask=None)[source]
Calculate tile airmass at given MJD.
- Parameters:
mjd (array) – Array of MJD to use. If mask is None, then should have length
self.ntiles. Otherwise, should have a value per non-zero entry in the mask.mask (array or None) – Boolean mask of which tiles to perform the calculation for.
- Returns:
Array of airmasses corresponding to each input hour angle.
- Return type:
array
- airmass_second_derivative(HA, mask=None)[source]
Calculate second derivative of airmass with HA.
Useful for determining how close to design airmass we have to get for different tiles. When this is large, we really need to observe things right at their design angles. When it’s small, we have more flexibility.
- property fiberassign_delay
Delay between covering a tile and when it can be fiber assigned.
Units are determined by the value of the fiber_assignment_cadence configuration parameter.
- index(tileID, return_mask=False)[source]
Map tile ID to array index.
- Parameters:
- Returns:
Index into internal per-tile arrays corresponding to each input tile ID.
- Return type:
int or array
- property neighbors
Dictionary of tile neighbor matrices.
neighbors[i] is the list of tile row numbers that neighbor the tile with row number i within a pass.
Neighboring tiles are only computed within a program and pass.
- property overlapping
Dictionary of tile overlap matrices.
overlapping[i] is the list of tile row numbers that overlap the tile with row number i.
Overlapping tiles are only computed within a program; a tile cannot overlap a tile of a different program. If fiber_assignment_delay is negative, tile do not overlap one another within a program.
- desisurvey.tiles.get_nominal_program_times(tileprogram, config=None, return_timetypes=False)[source]
Return nominal times for given programs in seconds.
- desisurvey.tiles.get_tiles(tiles_file=None, use_cache=True, write_cache=True)[source]
Return a Tiles object with optional caching.
You should normally always use the default arguments to ensure that tiles are defined consistently and efficiently between different classes.
- Parameters:
tiles_file (str or None) – Use the specified name to override config.tiles_file.
use_cache (bool) – Use tiles previously cached in memory when True. Otherwise, (re)load tiles from disk.
write_cache (bool) – If tiles need to be loaded from disk with this call, save them in a memory cache for future calls.
desisurvey.utils
Utility functions for survey planning and scheduling.
- desisurvey.utils.cos_zenith(ha, dec, latitude=None)[source]
Calculate cos(zenith) for specified hour angle, DEC and latitude.
Combine with
cos_zenith_to_airmass()to calculate airmass.- Parameters:
ha (astropy.units.Quantity) – Hour angle(s) to use, with units convertible to angle.
dec (astropy.units.Quantity) – Declination angle(s) to use, with units convertible to angle.
latitude (astropy.units.Quantity or None) – Latitude angle to use, with units convertible to angle. Defaults to the latitude of
get_location()if None.
- Returns:
cosine of zenith angle(s) corresponding to the inputs.
- Return type:
numpy array
- desisurvey.utils.cos_zenith_to_airmass(cosZ)[source]
Convert a zenith angle to an airmass.
Uses the Rozenberg 1966 interpolation formula, which gives reasonable results for high zenith angles, with a horizon air mass of 40. https://en.wikipedia.org/wiki/Air_mass_(astronomy)#Interpolative_formulas Rozenberg, G. V. 1966. “Twilight: A Study in Atmospheric Optics.” New York: Plenum Press, 160.
The value of cosZ is clipped to [0,1], so observations below the horizon return the horizon value (~40).
- desisurvey.utils.day_number(date)[source]
Return the number of elapsed days since the start of the survey.
Does not perform any range check that the date is within the nominal survey schedule.
- Parameters:
date (astropy.time.Time, datetime.date, datetime.datetime, string or number) – Converted to a date using
get_date().- Returns:
Number of elapsed days since the start of the survey.
- Return type:
- desisurvey.utils.get_airmass(when, ra, dec)[source]
Return the airmass of (ra,dec) at the specified observing time.
Uses
cos_zenith_to_airmass().- Parameters:
when (astropy.time.Time) – Observation time, which specifies the local zenith.
ra (astropy.units.Quantity) – Target RA angle(s)
dec (astropy.units.Quantity) – Target DEC angle(s)
- Returns:
Value of the airmass for each input (ra,dec).
- Return type:
array or float
- desisurvey.utils.get_average_dome_closed_fractions(first, last, smooth=7)[source]
Get daily averaged dome-closed fractions between first and last.
Returns the fraction of the time the dome is closed on each night.
- Parameters:
first (datetime.date) – Date of first night.
last (datetime.date) – Date of last night. Survey stops the morning of this date.
smooth (float) – Number of days to smooth dome closed fraction by.
- Return type:
np.ndarray giving dome closed fraction on each night.
- desisurvey.utils.get_current_date()[source]
Give current date following get_date convention (date changes at noon).
- Return type:
datetime.date object for current night, following get_date convention
- desisurvey.utils.get_date(date)[source]
Convert different date specifications into a datetime.date object.
We use strptime() to convert an input string, so leading zeros are not required for strings in the format YYYY-MM-DD, e.g. 2019-8-3 is considered valid.
Instead of testing the input type, we try different conversion methods:
.datetime.date()for an astropy time anddatetime.date()for a datetime.Date specifications that include a time of day (datetime, astropy time, MJD) are rounded down to the previous local noon before converting to a date. This ensures that all times during a local observing night are mapped to the same date, when the night started. A “naive” (un-localized) datetime is assumed to refer to UTC.
Generates astropy ERFA warnings for future dates.
- Parameters:
date (astropy.time.Time, datetime.date, datetime.datetime, string or number) – Specification of the date to return. A string must have the format YYYY-MM-DD (but leading zeros on MM and DD are optional). A number will be interpreted as a UTC MJD value.
- Return type:
- desisurvey.utils.get_location()[source]
Return the telescope’s earth location.
The location object is cached after the first call, so there is no need to cache this function’s return value externally.
- Return type:
- desisurvey.utils.get_observer(when, alt=None, az=None)[source]
Return the AltAz frame for the telescope at the specified time(s).
Refraction corrections are not applied (for now).
The returned object is automatically broadcast over input arrays.
- Parameters:
when (astropy.time.Time) – One or more times when the AltAz transformations should be calculated.
alt (astropy.units.Quantity or None) – Local altitude angle(s)
az (astropy.units.Quantity or None) – Local azimuth angle(s)
- Returns:
AltAz frame object suitable for transforming to/from local horizon (alt, az) coordinates.
- Return type:
- desisurvey.utils.is_monsoon(night)[source]
Test if this night’s observing falls in the monsoon shutdown.
Uses the monsoon date ranges defined in the
desisurvey.config.Configuration.- Parameters:
night (date) – Converted to a date using
desisurvey.utils.get_date().- Returns:
True if this night’s observing falls during the monsoon shutdown.
- Return type:
- desisurvey.utils.local_noon_on_date(day)[source]
Convert a date to an astropy time at local noon.
Local noon is used as the separator between observing nights. The purpose of this function is to standardize the boundary between observing nights and the mapping of dates to times.
Generates astropy ErfaWarnings for times in the future.
- Parameters:
day (datetime.date) – The day to use for generating a time object.
- Returns:
A Time object with the input date and a time corresponding to local noon at the telescope.
- Return type:
- desisurvey.utils.match(a, b)[source]
Find matching elements of b in unique array a by index.
Returns indices ma, mb such that a[ma] == b[mb]
- Parameters:
a (unique array)
b (array)
- Returns:
ma, mb
- Return type:
indices such that a[ma] == b[mb]
- desisurvey.utils.night_to_str(date)[source]
Return DESI string format (YYYYMMDD) of datetime night.
- Parameters:
date (datetime.date object, as from get_date())
- Returns:
YYYMMDD formatted date string
- Return type:
- desisurvey.utils.separation_matrix(ra1, dec1, ra2, dec2, max_separation=None)[source]
Build a matrix of pair-wise separation between (ra,dec) pointings.
The ra1 and dec1 arrays must have the same shape. The ra2 and dec2 arrays must also have the same shape, but it can be different from the (ra1,dec1) shape, resulting in a non-square return matrix.
Uses the Haversine formula for better accuracy at low separations. See https://en.wikipedia.org/wiki/Haversine_formula for details.
Equivalent to using the separations() method of astropy.coordinates.ICRS, but faster since it bypasses any units.
- Parameters:
ra1 (array) – 1D array of n1 RA coordinates in degrees (without units attached).
dec1 (array) – 1D array of n1 DEC coordinates in degrees (without units attached).
ra2 (array) – 1D array of n2 RA coordinates in degrees (without units attached).
dec2 (array) – 1D array of n2 DEC coordinates in degrees (without units attached).
max_separation (float or None) – When present, the matrix elements are replaced with booleans given by (value <= max_separation), which saves some computation.
- Returns:
Array with shape (n1,n2) with element [i1,i2] giving the 3D separation angle between (ra1[i1],dec1[i1]) and (ra2[i2],dec2[i2]) in degrees or, if max_separation is not None, booleans (value <= max_separation).
- Return type:
array
- desisurvey.utils.slewtime(ra1, dec1, ra2, dec2, freeslewtime=10, ignore_positive_ra=False)[source]
Estimate slew times.
Uses slew model from DESI-3687. Assumes that freeslewtime s of slew time is “free”—i.e., it can be overlapped with other overheads.
- Parameters:
ra1 (float) – right ascension (deg)
dec1 (float) – declination (deg)
ra2 (float) – right ascension (deg)
dec2 (float) – declination (deg)
freeslewtime (float) – amount of time during which one can slew “for free” (s)
ignore_positive_ra (float) – if True, slew time in the positive RA direction doesn’t count. Intended to provide no penalty for slews that are just keeping up with the sky. In this case, slews in dec don’t count if they fit within the slew in RA.
- Return type:
Estimated slew time in s needed to reach target.
Command-Line Scripts
afternoon_plan
- desisurvey.scripts.afternoon_plan.afternoon_plan(night=None, exposures=None, configfn='config.yaml', spectra_dir=None, desisurvey_output=None, nts_dir=None, sv=False, surveyops=None, skip_mtl_done_range=None, moonsep=50, no_network=False)[source]
Perform daily afternoon planning.
Afternoon planning identifies tiles available for observation and assigns priorities. It must be performed before the NTS can identify new tiles to observe.
Params
- nightstr
Night to plan (YYYMMDD). Default tonight.
- exposuresstr
File name of exposures file to restore. Default of None looks in $SURVEYOPS/ops/exposures.csv.
- configfnstr
File name of desisurvey config to use for plan.
- spectra_dirstr
Directory where spectra are found.
- desisurvey_outputstr
Afternoon planning config is stored to desisurvey_output/{night}/. Default to DESISURVEY_OUTPUT if None.
- nts_dirstr
Store afternoon planning to desisurvey_output/{nts_dir} rather than to desisurvey_output/{night}. Default to None.
- svbool
if True, trigger special tweaking of OBSCONDITIONS in tile file, donefrac in status file.
- surveyopsstr
surveyops SVN directory. Default of None triggers looking at the SURVEYOPS environment variable.
- skip_mtl_done_range[[float, float], …], or None
Don’t set status = DONE for any tiles using the mtl-done-tiles with range[0] <= ZDATE <= range[1], for range in skip_mtl_done_range. This prevents overlapping these tiles.
- no_networkbool
Skip svn & wget steps.
collect_etc
- desisurvey.scripts.collect_etc.cull_old_files(files, start_from)[source]
Return only subset of files with EXPID larger than any EXPID in start_from.
- desisurvey.scripts.collect_etc.get_conditions(mjd)[source]
Determine DARK/GRAY/BRIGHT for a set of exposures.
- Parameters:
mjd (array of mjds to query)
- Returns:
conditions
- Return type:
array of strings DARK, GRAY, BRIGHT, UNKNOWN
- desisurvey.scripts.collect_etc.read_exp(fn)[source]
Read tile & exposure ETC statistics file from filename.
This function works around some fits string issues in old versions of astropy.
- Parameters:
fn (str)
- Returns:
tiles, exps
numpy arrays for the tile and exposure ETC files
- desisurvey.scripts.collect_etc.scan_directory(dirname, start_from=None, offlinedepth=None, mtldone=None, offlinetiles=None, badexp=None)[source]
Scan directory for spectra with ETC statistics to collect.
- Parameters:
dirname (str) – directory path to scan. All fits files under dirname are searched for ETC statistics. This needs to be updated to ~DESI files only, with more care given to where these keywords are actually found.
start_from (str) – etc_stats file to start from. Nights already in the etc_stats file will not be collected. If a YYYMMDD string, look for etc_stats file in DESISURVEY_OUTPUT/YYYYMMDD/etc_stats-{YYYYMMDD}.fits None indicates starting fresh.
offlinedepth (str) – offline depth file to use. Fills out donefracs according to R_DEPTH in the file, plus config.nominal_exposure_time
offlinetiles (str) – offline tile completeness file to use. Fills out obsstatus according to OBSSSTATUS in the file.
mtldone (str) – mtl done file to use. Fills out done status according to presence in mtl done file.
badexp (str) – bad exposure file to use. EXPID marked bad in this file are also marked bad in the exposures file.
run_plan
surveyinit
Script wrapper for initializing survey planning and scheduling.
This is normally run once, at the start of the survey, and saves its results to a FITS file surveyinit.fits. With the default parameters, the running time is about 25 minutes.
This script will calculate the ephemerides and expected weather (dome open
fraction) for 2019-2025, then calculate design hour angles for the
nominal survey dates. The results are saved in a file (normally
surveyinit.fits) and then do not need to be recalculated ever again.
To run this script from the command line, use the surveyinit entry point
that is created when this package is installed, and should be in your shell
command search path.
- desisurvey.scripts.surveyinit.calculate_initial_plan(args)[source]
Calculate the initial survey plan.
Use
desisurvey.plan.load_weather()anddesisurvey.plan.load_design_hourangles()to retrieve these data from the saved plan.- Parameters:
args (object) – Object with attributes for parsed command-line arguments.
surveymovie
Script wrapper for creating a movie of survey progress.
To run this script from the command line, use the surveymovie entry point
that is created when this package is installed, and should be in your shell
command search path.
The optional matplotlib python package must be installed to use this script.
The external program ffmpeg must be installed to use this script.
At nersc, try module add ffmpeg.
- class desisurvey.scripts.surveymovie.Animator(exposures_path, start, stop, label, show_scores)[source]
Manage animation of survey progress.
- draw_exposure(iexp, nightly)[source]
Draw the frame for a single exposure.
Calls
init_date()if this is the first exposure of the night that we have seen.
- init_date(date, ephem)[source]
Initialize before drawing frames for a new night.
- Parameters:
date (datetime.date) – Date on which this night’s observing starts.
night (astropy.table.Column) – Ephemerides data for this night.
- desisurvey.scripts.surveymovie.main(args)[source]
Command-line driver to visualize survey scheduling and progress.