Source code for rubin_scheduler.scheduler.surveys.generate_ddf_grid

__all__ = ("generate_ddf_grid",)

import os
import sys

import astropy.units as u
import numpy as np
from astropy.time import Time

from rubin_scheduler.data import get_data_dir
from rubin_scheduler.site_models.seeing_model import SeeingModel
from rubin_scheduler.utils import Site, ddf_locations, m5_flat_sed


[docs] def generate_ddf_grid( verbose=True, mjd0=59560.2, delta_t=15.0, survey_length=40.0, sun_limit=-12, nominal_expt=30.0, ): """Pre-compute conditions for DDF locations over survey Parameters ---------- mjd0 : `float` The start MJD of the grid delta_t : `float` Spacing of time steps in minutes. Default 15 survey_length : `float` Full span of DDF grid (years). Default 40. sun_limit : `float` Ignore times with sun above sun limit in degrees. Default -12. nominal_expt : `float` Nominal exposure time in seconds to use for depth visits. Default 30 """ # Technically this script should be over in rubin_sim, but here to be more # easily found. Bury import here so it's hopefully not a problem. import rubin_sim.skybrightness as sb from astroplan import Observer dds = ddf_locations() delta_t = delta_t / 60.0 / 24.0 # to days survey_length = survey_length * 365.25 sun_limit = np.radians(sun_limit) # degrees nominal_seeing = 0.7 # arcsec site = Site("LSST") observer = Observer( longitude=site.longitude * u.deg, latitude=site.latitude * u.deg, elevation=site.height * u.m, name="LSST", ) seeing_model = SeeingModel() seeing_indx = 1 # 0=u, 1=g, 2=r, etc. mjds = np.arange(mjd0, mjd0 + survey_length, delta_t) names = ["mjd", "sun_alt", "sun_n18_rising_next"] for survey_name in dds.keys(): names.append(survey_name + "_airmass") names.append(survey_name + "_sky_g") names.append(survey_name + "_m5_g") types = [float] * len(names) result = np.zeros(mjds.size, dtype=list(zip(names, types))) result["mjd"] = mjds # pretty sure these are radians ras = np.radians(np.array([dds[survey][0] for survey in dds])) decs = np.radians(np.array([dds[survey][1] for survey in dds])) sm = sb.SkyModel(mags=True) mags = [] airmasses = [] sun_alts = [] maxi = mjds.size for i, mjd in enumerate(mjds): if verbose: progress = i / maxi * 100 text = "\rprogress = %0.1f%%" % progress sys.stdout.write(text) sys.stdout.flush() try: sm.set_ra_dec_mjd(ras, decs, mjd, degrees=False) except ValueError: sm.sun_alt = 12.0 if sm.sun_alt > sun_limit: mags.append(sm.return_mags()["g"] * 0) airmasses.append(sm.airmass * 0) else: mags.append(sm.return_mags()["g"]) airmasses.append(sm.airmass) sun_alts.append(sm.sun_alt) result["sun_n18_rising_next"][i] = observer.twilight_morning_astronomical( Time(mjd, format="mjd"), which="next" ).mjd mags = np.array(mags) airmasses = np.array(airmasses) result["sun_alt"] = sun_alts for i, survey_name in enumerate(dds.keys()): result[survey_name + "_airmass"] = airmasses[:, i] result[survey_name + "_sky_g"] = mags[:, i] # now to compute the expected seeing if the zenith is nominal FWHMeff = seeing_model(nominal_seeing, airmasses[:, i])["fwhmEff"][seeing_indx, :] result[survey_name + "_m5_g"] = m5_flat_sed( "g", mags[:, i], FWHMeff, nominal_expt, airmasses[:, i], nexp=1 ) return result
if __name__ == "__main__": # Generate a grid of airmass skybrightness values # for each DDF in 15 minute intervals. result = generate_ddf_grid() np.savez(os.path.join(get_data_dir(), "scheduler", "ddf_grid.npz"), ddf_grid=result)