Example #1
0
    def _setupPointGrid(self):
        """
        Setup the points for the interpolation functions.
        """
        # Switch to Dublin Julian Date for pyephem
        self.Observatory.date = mjd2djd(self.mjd)

        sun = ephem.Sun()
        sun.compute(self.Observatory)
        self.sunAlt = sun.alt
        self.sunAz = sun.az
        self.sunRA = sun.ra
        self.sunDec = sun.dec

        # Compute airmass the same way as ESO model
        self.airmass = 1./np.cos(np.pi/2.-self.alts)

        self.points['airmass'] = self.airmass
        self.points['nightTimes'] = 2
        self.points['alt'] = self.alts
        self.points['az'] = self.azs

        if self.twilight:
            self.points['sunAlt'] = self.sunAlt
            self.azRelSun = wrapRA(self.azs - self.sunAz)
            self.points['azRelSun'] = self.azRelSun

        if self.moon:
            moon = ephem.Moon()
            moon.compute(self.Observatory)
            self.moonPhase = moon.phase
            self.moonAlt = moon.alt
            self.moonAz = moon.az
            self.moonRA = moon.ra
            self.moonDec = moon.dec
            # Calc azimuth relative to moon
            self.azRelMoon = calcAzRelMoon(self.azs, self.moonAz)
            self.moonTargSep = haversine(self.azs, self.alts, self.moonAz, self.moonAlt)
            self.points['moonAltitude'] += np.degrees(self.moonAlt)
            self.points['azRelMoon'] += self.azRelMoon
            self.moonSunSep = self.moonPhase/100.*180.
            self.points['moonSunSep'] += self.moonSunSep

        if self.zodiacal:
            self.eclipLon = np.zeros(self.npts)
            self.eclipLat = np.zeros(self.npts)

            for i, temp in enumerate(self.ra):
                eclip = ephem.Ecliptic(ephem.Equatorial(self.ra[i], self.dec[i], epoch='2000'))
                self.eclipLon[i] += eclip.lon
                self.eclipLat[i] += eclip.lat
            # Subtract off the sun ecliptic longitude
            sunEclip = ephem.Ecliptic(sun)
            self.sunEclipLon = sunEclip.lon
            self.points['altEclip'] += self.eclipLat
            self.points['azEclipRelSun'] += wrapRA(self.eclipLon - self.sunEclipLon)

        self.mask = np.where((self.airmass > self.airmassLimit) | (self.airmass < 1.))[0]
        self.goodPix = np.where((self.airmass <= self.airmassLimit) & (self.airmass >= 1.))[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)
Example #3
0
    def _setupPointGrid(self):
        """
        Setup the points for the interpolation functions.
        """
        # Switch to Dublin Julian Date for pyephem
        self.Observatory.date = mjd2djd(self.mjd)

        sun = ephem.Sun()
        sun.compute(self.Observatory)
        self.sunAlt = sun.alt
        self.sunAz = sun.az
        self.sunRA = sun.ra
        self.sunDec = sun.dec

        # Compute airmass the same way as ESO model
        self.airmass = 1. / np.cos(np.pi / 2. - self.alts)

        self.points['airmass'] = self.airmass
        self.points['nightTimes'] = 2
        self.points['alt'] = self.alts
        self.points['az'] = self.azs

        if self.twilight:
            self.points['sunAlt'] = self.sunAlt
            self.azRelSun = wrapRA(self.azs - self.sunAz)
            self.points['azRelSun'] = self.azRelSun

        if self.moon:
            moon = ephem.Moon()
            moon.compute(self.Observatory)
            self.moonPhase = moon.phase
            self.moonAlt = moon.alt
            self.moonAz = moon.az
            self.moonRA = moon.ra
            self.moonDec = moon.dec
            # Calc azimuth relative to moon
            self.azRelMoon = calcAzRelMoon(self.azs, self.moonAz)
            self.moonTargSep = haversine(self.azs, self.alts, self.moonAz,
                                         self.moonAlt)
            self.points['moonAltitude'] += np.degrees(self.moonAlt)
            self.points['azRelMoon'] += self.azRelMoon
            self.moonSunSep = self.moonPhase / 100. * 180.
            self.points['moonSunSep'] += self.moonSunSep

        if self.zodiacal:
            self.eclipLon = np.zeros(self.npts)
            self.eclipLat = np.zeros(self.npts)

            for i, temp in enumerate(self.ra):
                eclip = ephem.Ecliptic(
                    ephem.Equatorial(self.ra[i], self.dec[i], epoch='2000'))
                self.eclipLon[i] += eclip.lon
                self.eclipLat[i] += eclip.lat
            # Subtract off the sun ecliptic longitude
            sunEclip = ephem.Ecliptic(sun)
            self.sunEclipLon = sunEclip.lon
            self.points['altEclip'] += self.eclipLat
            self.points['azEclipRelSun'] += wrapRA(self.eclipLon -
                                                   self.sunEclipLon)

        self.mask = np.where((self.airmass > self.airmassLimit)
                             | (self.airmass < 1.))[0]
        self.goodPix = np.where((self.airmass <= self.airmassLimit)
                                & (self.airmass >= 1.))[0]
    mjds = np.append(mjds, data['mjd'])
    mjds = np.unique(mjds)


# Generate starID table
starids = np.arange(ra.size)
f = open('starTable.dat', 'w')
for i,rai in enumerate(ra):
    print >>f, '%i,%f,%f,0' % (i,ra[i],dec[i])
f.close()

# Generate mjd table
f = open('mjdTable.dat', 'w')
mjdID = np.arange(mjds.size)
for mjdid,mjd in zip(mjdID,mjds):
    Observatory.date = mjd2djd(mjd)
    sun.compute(Observatory)
    moon.compute(Observatory)
    print >>f, '%i,%f,%f,%f,%f' % (mjdid, mjd, sun.alt, moon.alt, moon.phase)
f.close()


# now to loop through and write the obs table and the mjd table
names = ['mjd', 'ra','dec', 'm','alt', 'dm', 'sky', 'band']
types = [float]*7
types.append('|S1')

obsidMax = 0

f = open('obsTable.dat', 'w')
maxJ = float(len(allFiles))
Example #5
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)
Example #6
0
    def setRaDecMjd(self,
                    lon,
                    lat,
                    mjd,
                    degrees=False,
                    azAlt=False,
                    solarFlux=130.):
        """
        Set the sky parameters by computing the sky conditions on a given MJD and sky location.

        Ra and Dec in raidans or degrees.
        input ra, dec or az,alt w/ altAz=True
        solarFlux: solar flux in s.f.u. Between 50 and 310.
        """
        # Wrap in array just in case single points were passed
        if not type(lon).__module__ == np.__name__:
            if np.size(lon) == 1:
                lon = np.array([lon])
                lat = np.array([lat])
            else:
                lon = np.array(lon)
                lat = np.array(lat)
        if degrees:
            self.ra = np.radians(lon)
            self.dec = np.radians(lat)
        else:
            self.ra = lon
            self.dec = lat
        self.mjd = mjd
        if azAlt:
            self.azs = self.ra.copy()
            self.alts = self.dec.copy()
            self.ra, self.dec = _raDecFromAltAz(self.alts, self.azs,
                                                self.Observatory.lon,
                                                self.Observatory.lat, self.mjd)
        else:
            self.alts, self.azs, pa = _altAzPaFromRaDec(
                self.ra, self.dec, self.Observatory.lon, self.Observatory.lat,
                self.mjd)

        self.npts = self.ra.size
        self._initPoints()

        self.solarFlux = solarFlux
        self.points['solarFlux'] = self.solarFlux

        # Switch to Dublin Julian Date for pyephem
        self.Observatory.date = mjd2djd(self.mjd)

        sun = ephem.Sun()
        sun.compute(self.Observatory)
        self.sunAlt = sun.alt
        self.sunAz = sun.az

        # Compute airmass the same way as ESO model
        self.airmass = 1. / np.cos(np.pi / 2. - self.alts)

        self.points['airmass'] = self.airmass
        self.points['nightTimes'] = 2
        self.points['alt'] = self.alts
        self.points['az'] = self.azs

        if self.twilight:
            self.points['sunAlt'] = self.sunAlt
            self.points['azRelSun'] = wrapRA(self.azs - self.sunAz)

        if self.moon:
            moon = ephem.Moon()
            moon.compute(self.Observatory)
            self.moonPhase = moon.phase
            self.moonAlt = moon.alt
            self.moonAz = moon.az
            # Calc azimuth relative to moon
            self.azRelMoon = wrapRA(self.azs - self.moonAz)
            over = np.where(self.azRelMoon > np.pi)
            self.azRelMoon[over] = 2. * np.pi - self.azRelMoon[over]
            self.points['moonAltitude'] += np.degrees(self.moonAlt)
            self.points['azRelMoon'] += self.azRelMoon
            self.points['moonSunSep'] += self.moonPhase / 100. * 180.

        if self.zodiacal:
            self.eclipLon = np.zeros(self.npts)
            self.eclipLat = np.zeros(self.npts)

            for i, temp in enumerate(self.ra):
                eclip = ephem.Ecliptic(
                    ephem.Equatorial(self.ra[i], self.dec[i], epoch='2000'))
                self.eclipLon[i] += eclip.lon
                self.eclipLat[i] += eclip.lat
            # Subtract off the sun ecliptic longitude
            sunEclip = ephem.Ecliptic(sun)
            self.sunEclipLon = sunEclip.lon
            self.points['altEclip'] += self.eclipLat
            self.points['azEclipRelSun'] += wrapRA(self.eclipLon -
                                                   self.sunEclipLon)

        data.sort(order='mjd')

        umjd = np.unique(data['mjd'])

        left = np.searchsorted(data['mjd'], umjd)
        right = np.searchsorted(data['mjd'], umjd, side='right')

        altaz = np.zeros(data.size, dtype=zip(['alt','az'], [float]*2))
        moonAlt = np.zeros(data.size, dtype=float)

        print 'computing alts and azs'

        for j, (le, ri, mjd) in enumerate(zip(left,right,umjd)):
            Observatory.date = mjd2djd(mjd)
            sun.compute(Observatory)
            obs_metadata = ObservationMetaData(pointingRA=np.degrees(sun.ra),
                                                   pointingDec=np.degrees(sun.dec),
                                                   rotSkyPos=np.degrees(0),
                                                   mjd=mjd)
            alt, az, pa = _altAzPaFromRaDec(data['ra'][le:ri], data['dec'][le:ri], obs_metadata)
            az = wrapRA(az - sun.az)
            altaz['alt'][le:ri] += alt
            altaz['az'][le:ri] += az
            moon.compute(Observatory)
            moonAlt[le:ri] += moon.alt

        print 'making maps'
        good = np.where(moonAlt < 0)
        magMap[:,i] = _healbin(altaz['az'][good],altaz['alt'][good], data['sky'][good],
    def setRaDecMjd(self,lon,lat,mjd,degrees=False,azAlt=False,solarFlux=130.):
        """
        Set the sky parameters by computing the sky conditions on a given MJD and sky location.

        Ra and Dec in raidans or degrees.
        input ra, dec or az,alt w/ altAz=True
        solarFlux: solar flux in s.f.u. Between 50 and 310.
        """
        # Wrap in array just in case single points were passed
        if not type(lon).__module__ == np.__name__ :
            if np.size(lon) == 1:
                lon = np.array([lon])
                lat = np.array([lat])
            else:
                lon = np.array(lon)
                lat = np.array(lat)
        if degrees:
            self.ra = np.radians(lon)
            self.dec = np.radians(lat)
        else:
            self.ra = lon
            self.dec = lat
        self.mjd = mjd
        if azAlt:
            self.azs = self.ra.copy()
            self.alts = self.dec.copy()
            self.ra,self.dec = _raDecFromAltAz(self.alts,self.azs, self.Observatory.lon,
                                               self.Observatory.lat, self.mjd)
        else:
            self.alts,self.azs,pa = _altAzPaFromRaDec(self.ra, self.dec, self.Observatory.lon,
                                                      self.Observatory.lat, self.mjd)

        self.npts = self.ra.size
        self._initPoints()

        self.solarFlux = solarFlux
        self.points['solarFlux'] = self.solarFlux

        # Switch to Dublin Julian Date for pyephem
        self.Observatory.date = mjd2djd(self.mjd)

        sun = ephem.Sun()
        sun.compute(self.Observatory)
        self.sunAlt = sun.alt
        self.sunAz = sun.az

        # Compute airmass the same way as ESO model
        self.airmass = 1./np.cos(np.pi/2.-self.alts)

        self.points['airmass'] = self.airmass
        self.points['nightTimes'] = 2
        self.points['alt'] = self.alts
        self.points['az'] = self.azs

        if self.twilight:
            self.points['sunAlt'] = self.sunAlt
            self.points['azRelSun'] = wrapRA(self.azs - self.sunAz)

        if self.moon:
            moon = ephem.Moon()
            moon.compute(self.Observatory)
            self.moonPhase = moon.phase
            self.moonAlt = moon.alt
            self.moonAz = moon.az
            # Calc azimuth relative to moon
            self.azRelMoon = wrapRA(self.azs - self.moonAz)
            over = np.where(self.azRelMoon > np.pi)
            self.azRelMoon[over] = 2.*np.pi - self.azRelMoon[over]
            self.points['moonAltitude'] += np.degrees(self.moonAlt)
            self.points['azRelMoon'] += self.azRelMoon
            self.points['moonSunSep'] += self.moonPhase/100.*180.


        if self.zodiacal:
            self.eclipLon = np.zeros(self.npts)
            self.eclipLat = np.zeros(self.npts)

            for i,temp in enumerate(self.ra):
                eclip = ephem.Ecliptic(ephem.Equatorial(self.ra[i],self.dec[i], epoch='2000'))
                self.eclipLon[i] += eclip.lon
                self.eclipLat[i] += eclip.lat
            # Subtract off the sun ecliptic longitude
            sunEclip = ephem.Ecliptic(sun)
            self.sunEclipLon = sunEclip.lon
            self.points['altEclip'] += self.eclipLat
            self.points['azEclipRelSun'] += wrapRA(self.eclipLon - self.sunEclipLon)
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)
Example #10
0
          robustRMS(validationArr['frameZP'][good]))
    print('------')

    rmsArray.append((filterName, dark, gray, bright))

    # OK, want to look at residuals as a function of time-of-year and time-of-night.
    # Maybe just do this for dark time

    darkTime = np.where((resid != 0.) & (validationArr['moonAlt'] != -666)
                        & (validationArr['moonAlt'] < 0)
                        & (validationArr['sunAlt'] < -20.))[0]

    names = ['sinceSet', 'toSet']
    mjdInfo = np.zeros(darkTime.size, dtype=list(zip(names, types)))
    sun = ephem.Sun()
    djds = mjd2djd(validationArr['mjd'][darkTime])
    for i, djd in enumerate(djds):
        Observatory.date = djd
        mjdInfo['sinceSet'][i] = djd - Observatory.previous_setting(sun)
        mjdInfo['toSet'][i] = Observatory.next_setting(sun) - djd

    fig, ax = plt.subplots(1)
    residuals = resid[darkTime] - validationArr['frameZP'][darkTime]
    ax.plot(mjdInfo['sinceSet'] * 24., residuals, 'ko', alpha=0.2)
    ax.set_xlabel('Time Since Sunset (hours)')
    ax.set_ylabel('Observation-Model (mags)')
    ax.set_title('Zenith Dark Time Residuals, %s' % filterName)
    ax.set_ylim([-0.4, 1])
    fig.savefig('Plots/residTON_%s.pdf' % filterName)
    plt.close(fig)
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)
    print 'Twilight time adopted frame ZP rms = %f mag' % robustRMS(validationArr['frameZP'][good])
    print '------'

    rmsArray.append((filterName, dark,gray,bright))


    # OK, want to look at residuals as a function of time-of-year and time-of-night.
    #Maybe just do this for dark time

    darkTime = np.where( (resid != 0.) & (validationArr['moonAlt'] != -666) &
                         (validationArr['moonAlt'] < 0) & (validationArr['sunAlt'] < -20.))[0]

    names = ['sinceSet', 'toSet']
    mjdInfo = np.zeros(darkTime.size, dtype=zip(names,types))
    sun = ephem.Sun()
    djds = mjd2djd(validationArr['mjd'][darkTime])
    for i,djd in enumerate(djds):
        Observatory.date = djd
        mjdInfo['sinceSet'][i] = djd-Observatory.previous_setting(sun)
        mjdInfo['toSet'][i] = Observatory.next_setting(sun)-djd



    fig,ax = plt.subplots(1)
    residuals=resid[darkTime]-validationArr['frameZP'][darkTime]
    ax.plot(mjdInfo['sinceSet']*24., residuals, 'ko', alpha=0.2)
    ax.set_xlabel('Time Since Sunset (hours)')
    ax.set_ylabel('Observation-Model (mags)')
    ax.set_title('Zenith Dark Time Residuals, %s' % filterName)
    ax.set_ylim([-0.4,1])
    fig.savefig('Plots/residTON_%s.pdf' % filterName)