Ejemplo n.º 1
0
 def for_lsst(self):
     """A convenience function to set the observatory location for LSST.
     """
     lsst = simsUtils.Site(name='LSST')
     self.latitude_rad = math.radians(lsst.latitude)
     self.longitude_rad = math.radians(lsst.longitude)
     self.height = lsst.height
Ejemplo n.º 2
0
 def setDefaults(self):
     """Set defaults for the Cerro Pachon observing site.
     """
     lsst = simsUtils.Site(name="LSST")
     self.name = "Cerro Pachon"
     self.latitude = lsst.latitude
     self.longitude = lsst.longitude
     self.height = lsst.height
     self.pressure = lsst.pressure
     self.temperature = lsst.temperature
     self.relative_humidity = lsst.humidity
Ejemplo n.º 3
0
def readUserRegions(confFile, useExclusions=True):
    fieldRA = []
    fieldDec = []
    peakL = 25.
    taperL = 5
    taperB = 180.
    maxReach = 80.
    maxAirmass = 10.
    with open(confFile, 'r') as f:
        for line in f:
            vals = line.split()
            if len(vals) > 0:
                if vals[0] == 'userRegion':
                    ra, dec, _ = vals[2].split(',')
                    fieldRA.append(ra)
                    fieldDec.append(dec)
                elif vals[0] == 'taperL':
                    taperL = float(vals[2])
                elif vals[0] == 'taperB':
                    taperB = float(vals[2])
                elif vals[0] == 'peakL':
                    peakL = float(vals[2])
                elif vals[0] == 'maxReach':
                    maxReach = float(vals[2])
                elif vals[0] == 'MaxAirmass':
                    maxAirmass = float(vals[2])
    #print confFile, taperL, taperB, peakL, maxReach, maxAirmass
    fieldRA = np.array(fieldRA, dtype=float)
    fieldDec = np.array(fieldDec, dtype=float)
    if useExclusions:
        # Remove fields that would be excluded based on declimit from 'maxReach' and 'maxAirmass'.
        latLimit = np.degrees(np.arccos(1. / maxAirmass))
        site = simsUtils.Site(name='LSST')
        latSite = site.latitude
        minDec = np.max([latSite - latLimit, -1 * np.abs(maxReach)])
        maxDec = np.min([latSite + latLimit, np.abs(maxReach)])
        condition = np.where((minDec < fieldDec) & (fieldDec < maxDec))
        print confFile, minDec, maxDec
        fieldRA = fieldRA[condition]
        fieldDec = fieldDec[condition]
        # Remove fields that would be excluded by galactic exclusion zone.
        # (there are other limits that could come in due to airmass, but we won't deal with them here .. for now).
        galL, galB = simsUtils.galacticFromEquatorial(fieldRA, fieldDec)
        band = peakL - taperL
        if taperL != 0 and taperB != 0:
            condition = np.where((galL < 180.) & (
                np.abs(galB) > (peakL - (band * np.abs(galL) / taperB))))
            condition2 = np.where((galL > 180.) & (
                np.abs(galB) > (peakL -
                                (band * np.abs(galL - 360.) / taperB))))
            fieldRA = np.concatenate([fieldRA[condition], fieldRA[condition2]])
            fieldDec = np.concatenate(
                [fieldDec[condition], fieldDec[condition2]])
    return fieldRA, fieldDec
Ejemplo n.º 4
0
def controlAltAzFromRaDec(raRad_in, decRad_in, longRad, latRad, mjd):
    """
    Converts RA and Dec to altitude and azimuth

    @param [in] raRad is the RA in radians
    (observed geocentric)

    @param [in] decRad is the Dec in radians
    (observed geocentric)

    @param [in] longRad is the longitude of the observer in radians
    (positive east of the prime meridian)

    @param [in[ latRad is the latitude of the observer in radians
    (positive north of the equator)

    @param [in] mjd is the universal time expressed as an MJD

    @param [out] altitude in radians

    @param [out[ azimuth in radians

    see: http://www.stargazing.net/kepler/altaz.html#twig04
    """
    obs = utils.ObservationMetaData(mjd=utils.ModifiedJulianDate(UTC=mjd),
                                    site=utils.Site(longitude=np.degrees(longRad),
                                                    latitude=np.degrees(latRad),
                                                    name='LSST'))

    if hasattr(raRad_in, '__len__'):
        raRad, decRad = utils._observedFromICRS(raRad_in, decRad_in, obs_metadata=obs,
                                                epoch=2000.0, includeRefraction=True)
    else:
        raRad, decRad = utils._observedFromICRS(raRad_in, decRad_in,
                                                obs_metadata=obs, epoch=2000.0, includeRefraction=True)

    lst = utils.calcLmstLast(obs.mjd.UT1, longRad)
    last = lst[1]
    haRad = np.radians(last * 15.) - raRad

    sinDec = np.sin(decRad)
    cosLat = np.cos(latRad)
    sinLat = np.sin(latRad)
    sinAlt = sinDec*sinLat + np.cos(decRad)*cosLat*np.cos(haRad)
    altRad = np.arcsin(sinAlt)
    azRad = np.arccos((sinDec - sinAlt*sinLat) / (np.cos(altRad)*cosLat))
    azRadOut = np.where(np.sin(haRad) >= 0.0, 2.0 * np.pi - azRad, azRad)
    if isinstance(altRad, float):
        return altRad, float(azRadOut)
    return altRad, azRadOut
Ejemplo n.º 5
0
    def testAltAzFromRaDec(self):
        """
        Test conversion from RA, Dec to Alt, Az
        """

        nSamples = 100
        ra = self.rng.random_sample(nSamples)*2.0*np.pi
        dec = (self.rng.random_sample(nSamples)-0.5)*np.pi
        lon_rad = 1.467
        lat_rad = -0.234
        controlAlt, controlAz = controlAltAzFromRaDec(ra, dec,
                                                      lon_rad, lat_rad,
                                                      self.mjd)

        obs = utils.ObservationMetaData(mjd=utils.ModifiedJulianDate(UTC=self.mjd),
                                        site=utils.Site(longitude=np.degrees(lon_rad),
                                                        latitude=np.degrees(lat_rad),
                                                        name='LSST'))

        # verify parallactic angle against an expression from
        # http://www.astro.washington.edu/groups/APO/Mirror.Motions/Feb.2000.Image.Jumps/report.html#Image%20motion%20directions
        #
        ra_obs, dec_obs = utils._observedFromICRS(ra, dec, obs_metadata=obs, epoch=2000.0,
                                                  includeRefraction=True)

        lmst, last = utils.calcLmstLast(obs.mjd.UT1, lon_rad)
        hourAngle = np.radians(last * 15.0) - ra_obs
        controlSinPa = np.sin(hourAngle) * np.cos(lat_rad) / np.cos(controlAlt)

        testAlt, testAz, testPa = utils._altAzPaFromRaDec(ra, dec, obs)

        distance = utils.arcsecFromRadians(utils.haversine(controlAz, controlAlt, testAz, testAlt))
        self.assertLess(distance.max(), 0.0001)
        self.assertLess(np.abs(np.sin(testPa) - controlSinPa).max(), self.tolerance)

        # test non-vectorized version
        for r, d in zip(ra, dec):
            controlAlt, controlAz = controlAltAzFromRaDec(r, d, lon_rad, lat_rad, self.mjd)
            testAlt, testAz, testPa = utils._altAzPaFromRaDec(r, d, obs)
            lmst, last = utils.calcLmstLast(obs.mjd.UT1, lon_rad)
            r_obs, dec_obs = utils._observedFromICRS(r, d, obs_metadata=obs,
                                                     epoch=2000.0, includeRefraction=True)
            hourAngle = np.radians(last * 15.0) - r_obs
            controlSinPa = np.sin(hourAngle) * np.cos(lat_rad) / np.cos(controlAlt)
            distance = utils.arcsecFromRadians(utils.haversine(controlAz, controlAlt, testAz, testAlt))
            self.assertLess(distance, 0.0001)
            self.assertLess(np.abs(np.sin(testPa) - controlSinPa), self.tolerance)
Ejemplo n.º 6
0
    def testAltAzRADecRoundTrip(self):
        """
        Test that altAzPaFromRaDec and raDecFromAltAz really invert each other
        """

        mjd = 58350.0

        alt_in = []
        az_in = []
        for alt in np.arange(0.0, 90.0, 10.0):
            for az in np.arange(0.0, 360.0, 10.0):
                alt_in.append(alt)
                az_in.append(az)

        alt_in = np.array(alt_in)
        az_in = np.array(az_in)

        for lon in (0.0, 90.0, 135.0):
            for lat in (60.0, 30.0, -60.0, -30.0):

                obs = utils.ObservationMetaData(mjd=mjd,
                                                site=utils.Site(longitude=lon, latitude=lat, name='LSST'))

                ra_in, dec_in = utils.raDecFromAltAz(alt_in, az_in, obs)

                self.assertIsInstance(ra_in, np.ndarray)
                self.assertIsInstance(dec_in, np.ndarray)

                self.assertFalse(np.isnan(ra_in).any(), msg='there were NaNs in ra_in')
                self.assertFalse(np.isnan(dec_in).any(), msg='there were NaNs in dec_in')

                # test that passing them in one at a time gives the same answer
                for ix in range(len(alt_in)):
                    ra_f, dec_f = utils.raDecFromAltAz(alt_in[ix], az_in[ix], obs)
                    self.assertIsInstance(ra_f, np.float)
                    self.assertIsInstance(dec_f, np.float)
                    self.assertAlmostEqual(ra_f, ra_in[ix], 12)
                    self.assertAlmostEqual(dec_f, dec_in[ix], 12)

                alt_out, az_out, pa_out = utils.altAzPaFromRaDec(ra_in, dec_in, obs)

                self.assertFalse(np.isnan(pa_out).any(), msg='there were NaNs in pa_out')

                for alt_c, az_c, alt_t, az_t in \
                        zip(np.radians(alt_in), np.radians(az_in), np.radians(alt_out), np.radians(az_out)):
                    distance = utils.arcsecFromRadians(utils.haversine(az_c, alt_c, az_t, alt_t))
                    self.assertLess(distance, 0.2)
Ejemplo n.º 7
0
    def get_configure_dict(cls):
        """Get the configuration dictionary for the observatory location.

        Returns
        -------
        dict
            The configuration dictionary for the observatory location.
        """
        lsst = simsUtils.Site(name='LSST')
        conf_dict = {
            'obs_site': {
                'latitude': lsst.latitude,
                'longitude': lsst.longitude,
                'height': lsst.height
            }
        }
        return conf_dict
Ejemplo n.º 8
0
    def testSunMoon(self):
        """
        Test that the sun moon interpolation is good enough
        """
        if self.data_present:
            sm = self.sm
            telescope = utils.Site('LSST')
            Observatory = ephem.Observer()
            Observatory.lat = telescope.latitude_rad
            Observatory.lon = telescope.longitude_rad
            Observatory.elevation = telescope.height

            sun = ephem.Sun()
            moon = ephem.Moon()

            mjd1 = sm.info['mjds'][0]
            mjd2 = sm.info['mjds'][3]

            mjds = np.linspace(mjd1, mjd2, 20)

            # Demand Moon and Sun Positions match to within 3 arcmin
            arcmin_places = np.abs(np.floor(np.log10(3. / 60. / 180. *
                                                     np.pi))).astype(int)

            for mjd in mjds:
                Observatory.date = mjd2djd(mjd)
                sun.compute(Observatory)
                moon.compute(Observatory)
                pre_calced = sm.returnSunMoon(mjd)

                self.assertLess(np.abs(pre_calced['sunAlt'] - sun.alt),
                                arcmin_places)
                sun_dist = haversine(sun.ra, sun.dec, pre_calced['sunRA'],
                                     pre_calced['sunDec'])
                self.assertAlmostEqual(sun_dist, 0., places=arcmin_places)

                self.assertLess(np.abs(pre_calced['moonAlt'] - moon.alt),
                                arcmin_places)
                moon_dist = haversine(moon.ra, moon.dec, pre_calced['moonRA'],
                                      pre_calced['moonDec'])
                self.assertAlmostEqual(moon_dist, 0., places=arcmin_places)

                self.assertAlmostEqual(np.radians(pre_calced['moonSunSep']),
                                       np.radians(moon.phase / 100. * 180.),
                                       places=arcmin_places)
Ejemplo n.º 9
0
def generate_lookahead_tables(mjd0=59560.2,
                              mjd_max=59621.2,
                              timestep=5.,
                              timestep_max=20.,
                              outfile='generated_sky.npz',
                              outpath=None,
                              nside=32,
                              sunLimit=-12.,
                              fieldID=False,
                              airmass_limit=1.5,
                              dm=0.3,
                              verbose=True):
    """
    Use the sky brightness model and the astronomical sky model to generate map of whether
    the sky will be observable at a given point in time and space, based on airmass, sky
    brightness, and moon location. Each feature gets its own map, where a 0 means a field
    or healpixel is not observable, and a 1 means it is. For now these are always 0 or 1 
    but they are typed as floats to accomodate future improvements
    """

    sunLimit = np.radians(sunLimit)

    # Set the time steps
    timestep = timestep / 60. / 24.  # Convert to days
    timestep_max = timestep_max / 60. / 24.  # Convert to days
    # Switch the indexing to opsim field ID if requested

    # Look at the mjds and toss ones where the sun is up
    mjds = np.arange(mjd0, mjd_max + timestep, timestep)
    sunAlts = np.zeros(mjds.size, dtype=float)

    telescope = utils.Site('LSST')
    Observatory = ephem.Observer()
    Observatory.lat = telescope.latitude_rad
    Observatory.lon = telescope.longitude_rad
    Observatory.elevation = telescope.height

    sun = ephem.Sun()

    for i, mjd in enumerate(mjds):
        Observatory.date = mjd2djd(mjd)
        sun.compute(Observatory)
        sunAlts[i] = sun.alt

    mjds = mjds[np.where(sunAlts <= np.radians(sunLimit))]

    if fieldID:
        field_data = np.loadtxt('fieldID.dat',
                                delimiter='|',
                                skiprows=1,
                                dtype=list(
                                    zip(['id', 'ra', 'dec'],
                                        [int, float, float])))
        ra = field_data['ra']
        dec = field_data['dec']
    else:
        hpindx = np.arange(hp.nside2npix(nside))
        ra, dec = utils.hpid2RaDec(nside, hpindx)

    if verbose:
        print('using %i points on the sky' % ra.size)
        print('using %i mjds' % mjds.size)

        # Set up the sky brightness model
    sm = sb.SkyModel(mags=True)

    filter_names = [u'u', u'g', u'r', u'i', u'z', u'y']

    # Initialize the relevant lists
    sky_brightness = {u'airmass': np.zeros((len(mjds), len(ra)), dtype = float),\
     u'mjds': np.zeros((len(mjds), len(ra)), dtype = float),\
     u'moonangle': np.zeros((len(mjds), len(ra)), dtype = float) }
    vmjd = np.zeros(len(mjds))

    for filter_name in filter_names:
        sky_brightness[filter_name] = np.zeros((len(mjds), len(ra)),
                                               dtype=float)

    length = mjds[-1] - mjds[0]

    for i, mjd in enumerate(mjds):
        progress = (mjd - mjd0) / length * 100
        text = "\rprogress = %.1f%%" % progress
        sys.stdout.write(text)
        sys.stdout.flush()
        sm.setRaDecMjd(ra, dec, mjd, degrees=True)
        if sm.sunAlt <= sunLimit:
            mags = sm.returnMags()
            for key in filter_names:
                sky_brightness[key][
                    i] = mags[key] < 21.3  #placeholder skybrightness
            airmasscomp = np.bitwise_and(1.5 > sm.airmass, sm.airmass > 1.0)
            sky_brightness[u'airmass'][i] = airmasscomp
            moonangles = palpy.dsepVector(np.full_like(ra,sm.moonRA), np.full_like(dec,sm.moonDec),\
                np.deg2rad(ra), np.deg2rad(dec))
            sky_brightness[u'moonangle'][
                i] = moonangles > 0.698  #placeholder moon angle limit, ~40 degrees
            vmjd[i] = mjd

    print('')

    #     for key in dict_of_lists:
    #         dict_of_lists[key] = np.array(dict_of_lists[key])
    # #         print(len(dict_of_lists[key]))
    #     for key in sky_brightness:
    #         sky_brightness[key] = np.array(sky_brightness[key])

    np.savez_compressed(outfile, mjds=vmjd, look_ahead=sky_brightness)
Ejemplo n.º 10
0
    def test_raDecFromAltAz(self):
        """
        Test conversion of Alt, Az to Ra, Dec using data on the Sun

        This site gives the altitude and azimuth of the Sun as a function
        of time and position on the earth

        http://aa.usno.navy.mil/data/docs/AltAz.php

        This site gives the apparent geocentric RA, Dec of major celestial objects
        as a function of time

        http://aa.usno.navy.mil/data/docs/geocentric.php

        This site converts calendar dates into Julian Dates

        http://aa.usno.navy.mil/data/docs/JulianDate.php
        """

        hours = np.radians(360.0 / 24.0)
        minutes = hours / 60.0
        seconds = minutes / 60.0

        longitude_list = []
        latitude_list = []
        mjd_list = []
        alt_list = []
        az_list = []
        ra_app_list = []
        dec_app_list = []

        longitude_list.append(np.radians(-22.0 - 33.0 / 60.0))
        latitude_list.append(np.radians(11.0 + 45.0 / 60.0))
        mjd_list.append(2457364.958333 - 2400000.5)  # 8 December 2015 11:00 UTC
        alt_list.append(np.radians(41.1))
        az_list.append(np.radians(134.7))
        ra_app_list.append(16.0 * hours + 59.0 * minutes + 16.665 * seconds)
        dec_app_list.append(np.radians(-22.0 - 42.0 / 60.0 - 2.94 / 3600.0))

        longitude_list.append(np.radians(-22.0 - 33.0 / 60.0))
        latitude_list.append(np.radians(11.0 + 45.0 / 60.0))
        mjd_list.append(2457368.958333 - 2400000.5)  # 12 December 2015 11:00 UTC
        alt_list.append(np.radians(40.5))
        az_list.append(np.radians(134.7))
        ra_app_list.append(17.0 * hours + 16.0 * minutes + 51.649 * seconds)
        dec_app_list.append(np.radians(-23.0 - 3 / 60.0 - 50.35 / 3600.0))

        longitude_list.append(np.radians(145.0 + 23.0 / 60.0))
        latitude_list.append(np.radians(-64.0 - 5.0 / 60.0))
        mjd_list.append(2456727.583333 - 2400000.5)  # 11 March 2014, 02:00 UTC
        alt_list.append(np.radians(29.5))
        az_list.append(np.radians(8.2))
        ra_app_list.append(23.0 * hours + 24.0 * minutes + 46.634 * seconds)
        dec_app_list.append(np.radians(-3.0 - 47.0 / 60.0 - 47.81 / 3600.0))

        longitude_list.append(np.radians(145.0 + 23.0 / 60.0))
        latitude_list.append(np.radians(-64.0 - 5.0 / 60.0))
        mjd_list.append(2456731.583333 - 2400000.5)  # 15 March 2014, 02:00 UTC
        alt_list.append(np.radians(28.0))
        az_list.append(np.radians(7.8))
        ra_app_list.append(23.0 * hours + 39.0 * minutes + 27.695 * seconds)
        dec_app_list.append(np.radians(-2.0 - 13.0 / 60.0 - 18.32 / 3600.0))

        for longitude, latitude, mjd, alt, az, ra_app, dec_app in \
            zip(longitude_list, latitude_list, mjd_list, alt_list, az_list,
                ra_app_list, dec_app_list):

            obs = utils.ObservationMetaData(site=utils.Site(longitude=np.degrees(longitude),
                                                            latitude=np.degrees(latitude), name='LSST'),
                                            mjd=utils.ModifiedJulianDate(UTC=mjd))

            ra_icrs, dec_icrs = utils._raDecFromAltAz(alt, az, obs)
            ra_test, dec_test = utils._appGeoFromICRS(ra_icrs, dec_icrs, mjd=obs.mjd)

            distance = np.degrees(utils.haversine(ra_app, dec_app, ra_test, dec_test))
            # this is all the precision we have in the alt,az data taken from the USNO
            self.assertLess(distance, 0.1)

            correction = np.degrees(utils.haversine(ra_test, dec_test, ra_icrs, dec_icrs))
            self.assertLess(distance, correction)
Ejemplo n.º 11
0
def generate_sky(mjd0=59560.2,
                 mjd_max=59565.2,
                 timestep=5.,
                 timestep_max=15.,
                 outfile=None,
                 outpath=None,
                 nside=32,
                 sunLimit=-12.,
                 fieldID=False,
                 airmass_overhead=1.5,
                 dm=0.2,
                 airmass_limit=2.5,
                 moon_dist_limit=10.,
                 planet_dist_limit=2.,
                 alt_limit=86.5,
                 requireStride=3,
                 verbose=True):
    """
    Pre-compute the sky brighntess for a series of mjd dates at the LSST site.

    Parameters
    ----------
    mjd0 : float (9560.2)
        The starting MJD time
    duration : float
        The length of time to generate sky maps for (years)
    timestep : float (5.)
        The timestep between sky maps (minutes)
    timestep_max : float (20.)
        The maximum alowable timestep (minutes)
    outfile : str
        The name of the output file to save the results in
    nside : in (32)
        The nside to run the healpixel map at
    sunLimit : float (-12)
        The maximum altitude of the sun to try and generate maps for. MJDs with a higher
        sun altitude are dropped
    fieldID : bool (False)
        If True, computes sky magnitudes at OpSim field locations. If False
        computes at healpixel centers.
    airmass_overhead : float
        The airmass region to demand sky models are well matched before dropping
        and assuming the timestep can be interpolated
    dm : float
        If a skymap can be interpolated from neighboring maps with precision dm,
        that mjd is dropped.
    airmass_limit : float
        Pixels with an airmass greater than airmass_limit are masked
    moon_dist_limit : float
        Pixels (fields) closer than moon_dist_limit (degrees) are masked
    planet_dist_limit : float (2.)
        Pixels (fields) closer than planet_dist_limit (degrees) to Venus, Mars, Jupiter, or Saturn are masked
    alt_limit : float (86.5)
        Altitude limit of the telescope (degrees). Altitudes higher than this are masked.
    requireStride : int (3)
        Require every nth mjd. Makes it possible to easily select an evenly spaced number states of a pixel.

    Returns
    -------
    dict_of_lists : dict
        includes key-value pairs:
        mjds : the MJD at every computation. Not evenly spaced as no computations.
        airmass : the airmass maps for each MJD
        masks : The boolean mask map for each MJD (True means the pixel should be masked)
        sunAlts : The sun altitude at each MJD
    sky_brightness : dict
        Has keys for each u,g,r,i,z,y filter. Each one is a 2-d array with dimensions of healpix ID and
        mjd (matched to the mjd list above).
    """

    sunLimit_rad = np.radians(sunLimit)
    alt_limit_rad = np.radians(alt_limit)

    # Set the time steps
    timestep = timestep / 60. / 24.  # Convert to days
    timestep_max = timestep_max / 60. / 24.  # Convert to days
    # Switch the indexing to opsim field ID if requested

    # Look at the mjds and toss ones where the sun is up
    mjds = np.arange(mjd0, mjd_max + timestep, timestep)
    sunAlts = np.zeros(mjds.size, dtype=float)

    if outfile is None:
        outfile = '%i_%i.npz' % (mjd0, mjd_max)
    if outpath is not None:
        outfile = os.path.join(outpath, outfile)

    telescope = utils.Site('LSST')
    Observatory = ephem.Observer()
    Observatory.lat = telescope.latitude_rad
    Observatory.lon = telescope.longitude_rad
    Observatory.elevation = telescope.height

    sun = ephem.Sun()

    # Planets we want to avoid
    planets = [ephem.Venus(), ephem.Mars(), ephem.Jupiter(), ephem.Saturn()]

    # Compute the sun altitude for all the possible MJDs
    for i, mjd in enumerate(mjds):
        Observatory.date = mjd2djd(mjd)
        sun.compute(Observatory)
        sunAlts[i] = sun.alt

    mjds = mjds[np.where(sunAlts <= sunLimit_rad)]
    required_mjds = mjds[::3]

    if fieldID:
        field_data = np.loadtxt('fieldID.dat',
                                delimiter='|',
                                skiprows=1,
                                dtype=list(
                                    zip(['id', 'ra', 'dec'],
                                        [int, float, float])))
        ra = field_data['ra']
        dec = field_data['dec']
    else:
        hpindx = np.arange(hp.nside2npix(nside))
        ra, dec = utils.hpid2RaDec(nside, hpindx)

    ra_rad = np.radians(ra)
    dec_rad = np.radians(dec)
    if verbose:
        print('using %i points on the sky' % ra.size)
        print('using %i mjds' % mjds.size)

    # Set up the sky brightness model
    sm = sb.SkyModel(mags=True, airmass_limit=airmass_limit)

    filter_names = ['u', 'g', 'r', 'i', 'z', 'y']

    # Initialize the relevant lists
    dict_of_lists = {
        'airmass': [],
        'sunAlts': [],
        'mjds': [],
        'airmass_masks': [],
        'planet_masks': [],
        'moonAlts': [],
        'moonRAs': [],
        'moonDecs': [],
        'sunRAs': [],
        'sunDecs': [],
        'moonSunSep': [],
        'moon_masks': [],
        'zenith_masks': []
    }
    sky_brightness = {}
    for filter_name in filter_names:
        sky_brightness[filter_name] = []

    length = mjds[-1] - mjds[0]
    last_5_mags = []
    last_5_mjds = []
    full_masks = []
    for mjd in mjds:
        progress = (mjd - mjd0) / length * 100
        text = "\rprogress = %.1f%%" % progress
        sys.stdout.write(text)
        sys.stdout.flush()
        sm.setRaDecMjd(ra, dec, mjd, degrees=True)
        if sm.sunAlt <= sunLimit_rad:
            mags = sm.returnMags()
            for key in filter_names:
                sky_brightness[key].append(mags[key])
            dict_of_lists['airmass'].append(sm.airmass)
            dict_of_lists['sunAlts'].append(sm.sunAlt)
            dict_of_lists['mjds'].append(mjd)
            dict_of_lists['sunRAs'].append(sm.sunRA)
            dict_of_lists['sunDecs'].append(sm.sunDec)
            dict_of_lists['moonRAs'].append(sm.moonRA)
            dict_of_lists['moonDecs'].append(sm.moonDec)
            dict_of_lists['moonSunSep'].append(sm.moonSunSep)
            dict_of_lists['moonAlts'].append(sm.moonAlt)
            last_5_mjds.append(mjd)
            last_5_mags.append(mags)
            if len(last_5_mjds) > 5:
                del last_5_mjds[0]
                del last_5_mags[0]

            masks = {
                'moon': None,
                'airmass': None,
                'planet': None,
                'zenith': None
            }
            for mask in masks:
                masks[mask] = np.zeros(np.size(ra), dtype=bool)
                masks[mask].fill(False)

            # Apply airmass masking limit
            masks['airmass'][np.where((sm.airmass > airmass_limit)
                                      | (sm.airmass < 1.))] = True

            # Apply moon distance limit
            masks['moon'][np.where(
                sm.moonTargSep <= np.radians(moon_dist_limit))] = True

            # Apply altitude limit
            masks['zenith'][np.where(sm.alts >= alt_limit_rad)] = True

            # Apply the planet distance limits
            Observatory.date = mjd2djd(mjd)
            for planet in planets:
                planet.compute(Observatory)
                distances = utils.haversine(ra_rad, dec_rad, planet.ra,
                                            planet.dec)
                masks['planet'][np.where(
                    distances <= np.radians(planet_dist_limit))] = True

            full_mask = np.zeros(np.size(ra), dtype=bool)
            full_mask.fill(False)
            for key in masks:
                dict_of_lists[key + '_masks'].append(masks[key])
                full_mask[masks[key]] = True
                full_masks.append(full_mask)

            if len(dict_of_lists['airmass']) > 3:
                if dict_of_lists['mjds'][-2] not in required_mjds:
                    # Check if we can interpolate the second to last sky brightnesses
                    overhead = np.where(
                        (dict_of_lists['airmass'][-1] <= airmass_overhead)
                        & (dict_of_lists['airmass'][-2] <= airmass_overhead)
                        & (~full_masks[-1]) & (~full_masks[-2]))

                    if (np.size(overhead[0]) >
                            0) & (dict_of_lists['mjds'][-1] -
                                  dict_of_lists['mjds'][-3] < timestep_max):
                        can_interp = True
                        for mjd2 in last_5_mjds:
                            mjd1 = dict_of_lists['mjds'][-3]
                            mjd3 = dict_of_lists['mjds'][-1]
                            if (mjd2 > mjd1) & (mjd2 < mjd3):
                                indx = np.where(last_5_mjds == mjd2)[0]
                                # Linear interpolation weights
                                wterm = (mjd2 - mjd1) / (mjd3 - mjd1)
                                w1 = 1. - wterm
                                w2 = wterm
                                for filter_name in filter_names:
                                    interp_sky = w1 * sky_brightness[
                                        filter_name][-3][overhead]
                                    interp_sky += w2 * sky_brightness[
                                        filter_name][-1][overhead]
                                    diff = np.abs(last_5_mags[int(
                                        indx)][filter_name][overhead] -
                                                  interp_sky)
                                    if np.size(diff[~np.isnan(diff)]) > 0:
                                        if np.max(diff[~np.isnan(diff)]) > dm:
                                            can_interp = False
                        if can_interp:
                            for key in dict_of_lists:
                                del dict_of_lists[key][-2]
                            for key in sky_brightness:
                                del sky_brightness[key][-2]
    print('')

    for key in dict_of_lists:
        dict_of_lists[key] = np.array(dict_of_lists[key])
    for key in sky_brightness:
        sky_brightness[key] = np.array(sky_brightness[key])

    import lsst.sims.skybrightness_pre
    version = lsst.sims.skybrightness_pre.version.__version__
    fingerprint = lsst.sims.skybrightness_pre.version.__fingerprint__
    # Generate a header to save all the kwarg info for how this run was computed
    header = {
        'mjd0': mjd0,
        'mjd_max': mjd_max,
        'timestep': timestep,
        'timestep_max': timestep_max,
        'outfile': outfile,
        'outpath': outpath,
        'nside': nside,
        'sunLimit': sunLimit,
        'fieldID': fieldID,
        'airmas_overhead': airmass_overhead,
        'dm': dm,
        'airmass_limit': airmass_limit,
        'moon_dist_limit': moon_dist_limit,
        'planet_dist_limit': planet_dist_limit,
        'alt_limit': alt_limit,
        'ra': ra,
        'dec': dec,
        'verbose': verbose,
        'required_mjds': required_mjds,
        'version': version,
        'fingerprint': fingerprint
    }

    np.savez(outfile, dict_of_lists=dict_of_lists, header=header)
    # Convert sky_brightness to a true array so it's easier to save
    types = [float] * len(sky_brightness.keys())
    result = np.zeros(sky_brightness[list(sky_brightness.keys())[0]].shape,
                      dtype=list(zip(sky_brightness.keys(), types)))
    for key in sky_brightness.keys():
        result[key] = sky_brightness[key]
    np.save(outfile[:-3] + 'npy', result)
Ejemplo n.º 12
0
def generate_sky(mjd0=59560.2, duration=0.01, timestep=5., timestep_max=20.,
                 outfile='generated_sky.npz', nside=32,
                 sunLimit=-12., fieldID=False, airmass_limit=1.5, dm=0.3, verbose=True):
    """
    Use the sky brightness model to generate a number of useful numpy arrays that can be used
    to look-up sky brighntess and other pre-computed info
    """

    sunLimit = np.radians(sunLimit)

    # Set the time steps
    mjd_max = mjd0 + duration*365.25
    timestep = timestep / 60. / 24.  # Convert to days
    timestep_max = timestep_max / 60. / 24.  # Convert to days
    # Switch the indexing to opsim field ID if requested

    # Look at the mjds and toss ones where the sun is up
    mjds = np.arange(mjd0, mjd_max+timestep, timestep)
    sunAlts = np.zeros(mjds.size, dtype=float)

    telescope = utils.Site('LSST')
    Observatory = ephem.Observer()
    Observatory.lat = telescope.latitude_rad
    Observatory.lon = telescope.longitude_rad
    Observatory.elevation = telescope.height


    sun = ephem.Sun()

    for i, mjd in enumerate(mjds):
        Observatory.date = mjd2djd(mjd)
        sun.compute(Observatory)
        sunAlts[i] = sun.alt

    mjds = mjds[np.where(sunAlts <= np.radians(sunLimit))]


    if fieldID:
        field_data = np.loadtxt('fieldID.dat', delimiter='|', skiprows=1,
                                dtype=list(zip(['id', 'ra', 'dec'], [int, float, float])))
        ra = field_data['ra']
        dec = field_data['dec']
    else:
        hpindx = np.arange(hp.nside2npix(nside))
        ra, dec = utils.hpid2RaDec(nside, hpindx)

    if verbose:
        print('using %i points on the sky' % ra.size)
        print('using %i mjds' % mjds.size)

    # Set up the sky brightness model
    sm = sb.SkyModel(mags=True)

    filter_names = ['u', 'g', 'r', 'i', 'z', 'y']

    # Initialize the relevant lists
    dict_of_lists = {'airmass': [], 'sunAlts': [], 'mjds': []}
    sky_brightness = {}
    for filter_name in filter_names:
        sky_brightness[filter_name] = []

    length = mjds[-1] - mjds[0]

    for mjd in mjds:
        progress = (mjd-mjd0)/length*100
        text = "\rprogress = %.1f%%"%progress
        sys.stdout.write(text)
        sys.stdout.flush()
        sm.setRaDecMjd(ra, dec, mjd, degrees=True)
        if sm.sunAlt <= sunLimit:
            mags = sm.returnMags()
            for key in filter_names:
                sky_brightness[key].append(mags[key])
            dict_of_lists['airmass'].append(sm.airmass)
            dict_of_lists['sunAlts'].append(sm.sunAlt)
            dict_of_lists['mjds'].append(mjd)
            # XXX don't toss things now.
            if False:
                # Check if we can interpolate the second to last sky brightnesses
                overhead = np.where((dict_of_lists['airmass'][-1] <= airmass_limit) &
                                    (dict_of_lists['airmass'][-2] <= airmass_limit))
                # XXX -- might need to also excude things near the moon
                if np.size(overhead[0]) > 0:
                    can_interp = True
                    mjd1 = dict_of_lists['mjds'][-3]
                    mjd2 = dict_of_lists['mjds'][-2]
                    mjd3 = dict_of_lists['mjds'][-1]
                    # Linear interpolation weights
                    wterm = (mjd2 - mjd1) / (mjd3-mjd1)
                    w1 = 1. - wterm
                    w2 = wterm
                    for filter_name in filter_names:
                        interp_sky = w1 * sky_brightness[filter_name][-3][overhead]
                        interp_sky += w2 * sky_brightness[filter_name][-1][overhead]
                        diff = np.abs(sky_brightness[filter_name][-2][overhead]-interp_sky)
                        if np.size(diff[~np.isnan(diff)]) > 0:
                            if np.max(diff[~np.isnan(diff)]) > dm:
                                can_interp = False
                    # If the timestep is getting big, don't interp even if you can
                    if (dict_of_lists['mjds'][-3] - dict_of_lists['mjds'][-2]) > timestep_max:
                        can_interp = False
                    if can_interp:
                        for key in dict_of_lists:
                            del dict_of_lists[key][-2]
                        for key in sky_brightness:
                            del sky_brightness[key][-2]
    print('')

    for key in dict_of_lists:
        dict_of_lists[key] = np.array(dict_of_lists[key])
    for key in sky_brightness:
        sky_brightness[key] = np.array(sky_brightness[key])

    np.savez(outfile, dict_of_lists = dict_of_lists, sky_brightness=sky_brightness)