Exemplo n.º 1
0
    def testmergedComp(self):
        """
        Test that the 3 components that have been merged return the
        same result if they are computed independently
        """

        sky1 = sb.SkyModel(twilight=False,
                           zodiacal=False,
                           moon=False,
                           lowerAtm=False,
                           upperAtm=False,
                           airglow=False,
                           scatteredStar=False,
                           mergedSpec=True)
        sky1.setRaDecMjd([36.], [-68.], 49353.18, degrees=True)

        sky2 = sb.SkyModel(twilight=False,
                           zodiacal=False,
                           moon=False,
                           lowerAtm=True,
                           upperAtm=True,
                           airglow=False,
                           scatteredStar=True,
                           mergedSpec=False)
        sky2.setRaDecMjd([36.], [-68.], 49353.18, degrees=True)

        dummy, spec1 = sky1.returnWaveSpec()
        dummy, spec2 = sky2.returnWaveSpec()

        np.testing.assert_almost_equal(spec1, spec2)
    def testMags(self):
        """
        Test that the interpolated mags are similar to mags computed from interpolated spectra
        """

        throughPath = os.path.join(getPackageDir('throughputs'),'baseline')
        filters = ['u','g','r','i','z','y']

        bps = []
        for filterName in filters:
            bp = np.loadtxt(os.path.join(throughPath, 'filter_%s.dat' % filterName),
                            dtype=zip(['wave','trans'],[float]*2 ))
            lsst_bp = Bandpass()
            lsst_bp.setBandpass(bp['wave'], bp['trans'])
            bps.append(lsst_bp)

        sm1 = sb.SkyModel()
        sm1.setRaDecMjd([36.],[-68.],49353.18, degrees=True)
        sm1.computeSpec()
        mags1 = []
        for bp in bps:
            mags1.append(sm1.computeMags(bandpass=bp))
        mags1 = np.array(mags1)

        sm2 = sb.SkyModel(mags=True)
        sm2.setRaDecMjd([36.],[-68.],49353.18, degrees=True)
        sm2.computeSpec()
        mag2 = sm2.computeMags()
        np.testing.assert_allclose(mags1,mag2.T, rtol=1e-4)
Exemplo n.º 3
0
    def __init__(self,
                 observatory='LSST',
                 hwBandpassDict=None,
                 pointings=None,
                 photparams=None,
                 airmass_limit=4.0,
                 mags=False,
                 preciseAltAz=True):
        """
        Parameters
        ----------
        observatory : 
        mags : 
        preciseAltAz :
        hwBandpassDict :
        photparams :
        pointings :
        airmass_limit :
        """
        self.sm = sb.SkyModel(observatory=observatory,
                              mags=mags,
                              preciseAltAz=preciseAltAz,
                              airmass_limit=airmass_limit)
        self.adb = AirmassDependentBandpass(hwBandpassDict)

        self.photparams = photparams
        if self.photparams == 'LSST':
            self.photparams = PhotometricParameters()
Exemplo n.º 4
0
def add_skybright(df):
    skyModel = skybrightness.SkyModel(mags=True)
    sims_skybright = np.zeros(len(df), float)
    t = time.time()
    for i, dfi in df.iterrows():
        airmass = dfi.airmass
        alts = dfi.altitude
        # Fake the airmass if we're over the limit.
        if airmass > skyModel.airmassLimit:
            airmass = skyModel.airmassLimit - 0.1
            alts = np.pi / 2. - np.arccos(1. / airmass)
        skyModel.setParams(airmass=np.array([airmass]),
                           azs=np.array([dfi.azimuth]),
                           alts=np.array([alts]),
                           moonPhase=dfi.moonPhase,
                           moonAlt=dfi.moonAlt,
                           moonAz=dfi.moonAZ,
                           sunAlt=dfi.sunAlt,
                           sunAz=dfi.sunAz,
                           sunEclipLon=dfi.sunEclipLon,
                           eclipLon=np.array([dfi.eclipLon]),
                           eclipLat=np.array([dfi.eclipLat]),
                           degrees=False,
                           filterNames=[dfi['filter']])
        mags = skyModel.returnMags()
        sims_skybright[i] = mags[dfi['filter']][0]
    dt, t = dtime(t)
    print('%f seconds to calculate %d skybrightnesses' % (dt, i))
    df['sims_skybright'] = sims_skybright
    return df
    def testSetups(self):
        """
        Check that things are the same if the model is set up with
        radecmjd or all the parameters independently
        """

        sm1 = sb.SkyModel()
        sm1.setRaDecMjd([36.],[-68.],49353.18, degrees=True)

        sm2 = sb.SkyModel()
        sm2.setParams( azs=sm1.azs, alts=sm1.alts,
                       moonPhase=sm1.moonPhase,
                       moonAlt=sm1.moonAlt, moonAz=sm1.moonAz,
                       sunAlt=sm1.sunAlt, sunAz=sm1.sunAz,
                       sunEclipLon=sm1.sunEclipLon, eclipLon=sm1.eclipLon,
                       eclipLat=sm1.eclipLat, solarFlux=sm1.solarFlux,
                       degrees=False)

        sm1.computeSpec()
        sm2.computeSpec()

        np.testing.assert_array_equal(sm1.spec, sm2.spec)

        # Check that the degrees kwarg works
        sm2.setParams( azs=np.degrees(sm1.azs), alts=np.degrees(sm1.alts),
                       moonPhase=sm1.moonPhase,
                       moonAlt=np.degrees(sm1.moonAlt), moonAz=np.degrees(sm1.moonAz),
                       sunAlt=np.degrees(sm1.sunAlt), sunAz=np.degrees(sm1.sunAz),
                       sunEclipLon=np.degrees(sm1.sunEclipLon), eclipLon=np.degrees(sm1.eclipLon),
                       eclipLat=np.degrees(sm1.eclipLat), solarFlux=sm1.solarFlux,
                       degrees=True)
        sm2.computeSpec()

        atList = ['azs', 'alts', 'moonPhase', 'moonAlt', 'moonAz', 'sunAlt', 'sunAz',
                  'sunEclipLon', 'eclipLon', 'eclipLat', 'solarFlux']

        # Check each attribute that should match
        for attr in atList:
            np.testing.assert_allclose(getattr(sm1,attr), getattr(sm2,attr))

        # Check the interpolation points
        for name in sm1.points.dtype.names:
            np.testing.assert_allclose(sm1.points[name], sm2.points[name])

        # Check the final output spectra
        np.testing.assert_allclose(sm1.spec, sm2.spec)
 def test90Deg(self):
     """
     Make sure we can look all the way to 90 degree altitude.
     """
     mjd =  56973.268218 #56995.22103
     sm = sb.SkyModel(mags=True)
     sm.setRaDecMjd(0.,90.,mjd, degrees=True, azAlt=True)
     sm.computeSpec()
     mags = sm.computeMags()
     assert(True not in np.isnan(mags))
     assert(True not in np.isnan(sm.spec))
Exemplo n.º 7
0
def calc_target_m5s(alt=65., fiducial_seeing=0.9, exptime=20.):
    """
    Use the skybrightness model to find some good target m5s
    """
    import lsst.sims.skybrightness as sb
    sm = sb.SkyModel(moon=False, twilight=False, mags=True)
    sm.setRaDecMjd(np.array([0.]), np.array([alt]), 49353.177645, degrees=True, azAlt=True)
    sky_mags = sm.returnMags()
    airmass = 1./np.cos(np.pi/2.-np.radians(alt))

    goal_m5 = {}
    for filtername in sky_mags:
        goal_m5[filtername] = m5_flat_sed(filtername, sky_mags[filtername], fiducial_seeing,
                                          exptime, airmass)

    return goal_m5
Exemplo n.º 8
0
def recalcmags(j):
    logfname = 'newres_{}.log'.format(j)
    tsplitstart = time.time()
    with open(logfname, 'w') as f:
        f.write('starting split {0} at time {1}\n'.format(j, tsplitstart))
    df = dfs[j]
    sm = sb.SkyModel(observatory='LSST', mags=False, preciseAltAz=True)
    skycalc = obscond.SkyCalculations(photparams="LSST", hwBandpassDict=hwbpdict)

    fname = 'newres{}.hdf'.format(j)
    df_res = skycalc.calculatePointings(df)
    with open(logfname, mode='a+') as f:
        f.write('dataframe calculated\n')
    df_res.to_hdf(fname, key='0')
    tsplitend = time.time()
    with open(logfname, mode='a+') as f:
        f.write('dataframe written at time {} \n'.format(tsplitend))
        f.write('For dataframe of size {0} time taken is {1}\n'.format(len(df_res), tsplitend - tsplitstart))
    return df_res
Exemplo n.º 9
0
    def testSBP(self):
        """
        Check that values are similar enough
        """
        if self.data_present:
            original_model = sb.SkyModel(mags=True)
            pre_calc_model = self.sm

            hpindx = np.arange(hp.nside2npix(pre_calc_model.header['nside']))
            ra, dec = utils.hpid2RaDec(pre_calc_model.header['nside'], hpindx)

            # Run through a number of mjd values
            step = 30. / 60. / 24.  # 30 minute timestep
            nmjd = 48
            mjds = np.arange(nmjd) * step + self.sm.info['mjds'][10] + 0.1

            # Tolerance for difference between true and interpolated airmass
            am_tol = 0.05
            am_limit = 3.

            # Where to check the magnitudes match
            mag_am_limit = 1.5
            mag_tol = 0.2  # mags

            for mjd in mjds:
                original_model.setRaDecMjd(ra, dec, mjd, degrees=True)
                if original_model.sunAlt < np.radians(-12.):
                    sky1 = original_model.returnMags()
                    sky2 = pre_calc_model.returnMags(mjd)
                    am1 = original_model.airmass
                    am2 = pre_calc_model.returnAirmass(mjd)
                    good_am = np.where((am1 >= 1.) & (am1 <= am_limit))
                    diff = am1[good_am] - am2[good_am]
                    # Check that the interpolated airmass is close
                    assert (np.max(np.abs(diff)) < am_tol)

                    for filtername in sky1:
                        good = np.where((am1 < mag_am_limit)
                                        & (sky2[filtername] != hp.UNSEEN)
                                        & (np.isfinite(sky1[filtername])))
                        diff = sky1[filtername][good] - sky2[filtername][good]
                        assert (np.max(np.abs(diff)) <= mag_tol)
Exemplo n.º 10
0
    def __init__(self,
                 obs_metadata,
                 photParams,
                 seed=None,
                 bandpassDict=None,
                 addNoise=True,
                 addBackground=True,
                 logger=None):
        """
        @param [in] addNoise is a boolean telling the wrapper whether or not
        to add noise to the image

        @param [in] addBackground is a boolean telling the wrapper whether
        or not to add the skybackground to the image

        @param [in] seed is an (optional) int that will seed the
        random number generator used by the noise model. Defaults to None,
        which causes GalSim to generate the seed from the system.
        """

        self.obs_metadata = obs_metadata
        self.photParams = photParams

        if bandpassDict is None:
            self.bandpassDict = BandpassDict.loadBandpassesFromFiles()[0]

        # Computing the skybrightness.SkyModel object is expensive, so
        # do it only once in the constructor.
        self.skyModel = skybrightness.SkyModel(mags=False)

        self.addNoise = addNoise
        self.addBackground = addBackground
        if logger is not None:
            self.logger = logger
        else:
            self.logger = get_logger('INFO')

        if seed is None:
            self.randomNumbers = galsim.UniformDeviate()
        else:
            self.randomNumbers = galsim.UniformDeviate(seed)
Exemplo n.º 11
0
def generate_sky_slopes():
    """
    Fit a line to how the sky brightness changes with airmass.
    """
    import lsst.sims.skybrightness as sb
    import healpy as hp
    sm = sb.SkyModel(mags=True, moon=False, twilight=False, zodiacal=False)
    mjd = 57000
    nside = 32
    airmass_limit = 2.0
    dec, ra = hp.pix2ang(nside,np.arange(hp.nside2npix(nside)))
    dec = np.pi/2 - dec
    sm.setRaDecMjd(ra,dec,mjd)
    mags = sm.returnMags()
    filters = mags.dtype.names
    filter_slopes = {}
    for filterName in filters:
        good = np.where((~np.isnan(mags[filterName])) & (sm.airmass < airmass_limit))
        pf = np.polyfit(sm.airmass[good], mags[filterName][good], 1)
        filter_slopes[filterName] = pf[0]
    print filter_slopes
Exemplo n.º 12
0
    def test_skycounts_function(self):
        """
        Test that the SkyCountsPerSec class gives the right result for the previously
        calculated zero points. (This is defined as the number of counts per second for
        a 24 magnitude source.)  Here we set magNorm=24 to calculate the zero points
        but when calculating the sky background from the sky brightness
        model magNorm=None as above.
        """

        desc.imsim.read_config()
        instcat_file = os.path.join(os.environ['IMSIM_DIR'], 'tests',
                                    'tiny_instcat.txt')
        _, phot_params, _ = desc.imsim.parsePhoSimInstanceFile(instcat_file)
        skyModel = skybrightness.SkyModel(mags=False)
        skyModel.setRaDecMjd(0., 90., 58000, azAlt=True, degrees=True)

        bandPassdic = BandpassDict.loadTotalBandpassesFromFiles(['u', 'g', 'r', 'i', 'z', 'y'])
        skycounts_persec = desc.imsim.skyModel.SkyCountsPerSec(skyModel, phot_params, bandPassdic)

        skycounts_persec_u = skycounts_persec('u', 24)
        self.assertAlmostEqual(skycounts_persec_u.value, self.zp_u)
Exemplo n.º 13
0
 def sm_mags2(self):
     cls = type(self)
     if cls._sm_mags2 is None:
         cls._sm_mags2 = sb.SkyModel(mags=True)
     return cls._sm_mags2
Exemplo n.º 14
0
import numpy as np
import healpy as hp
from medDB import medDB, single_frame
from lsst.sims.utils import haversine
import lsst.sims.skybrightness as sb

nside = 32
filter_name = 'R'
sm = sb.SkyModel(
    mags=True)  #sb.SkyModel(mags=True, airglow=False, mergedSpec=False)
dec, ra = hp.pix2ang(nside, np.arange(hp.nside2npix(nside)))
dec = np.pi / 2 - dec
moonLimit = 30.  # Degrees
am_limit = 3.


def diff_image(mjd, mjd2, filter_name='R'):
    """
	Let's just load up a single image and difference it with the one taken before
	"""
    sm.setRaDecMjd(ra, dec, mjd)
    frame = single_frame(mjd, filter_name=filter_name)
    dist2moon = haversine(sm.azs, sm.alts, sm.moonAz, sm.moonAlt)
    frame[np.where(dist2moon < np.radians(moonLimit))] = hp.UNSEEN
    template_frame = single_frame(mjd2, filter_name=filter_name)
    good = np.where((frame != hp.UNSEEN) & (template_frame != hp.UNSEEN)
                    & (sm.airmass >= 1.) & (sm.airmass <= am_limit)
                    & (~np.isnan(frame)) & (~np.isnan(template_frame)))
    diff = np.zeros(frame.size, dtype=float) + hp.UNSEEN
    diff[good] = frame[good] - template_frame[good]
    return diff
Exemplo n.º 15
0
types.append(int)
results = np.zeros((mjds.size, map_size), dtype=list(zip(names, types)))
results['mask'] = 1
site = Site('LSST')

moon = ephem.Moon()
venus = ephem.Venus()
sun = ephem.Sun()
doff = ephem.Date(0) - ephem.Date('1858/11/17')

lsstObs = ephem.Observer()
lsstObs.lat = np.radians(site.latitude)
lsstObs.lon = np.radians(site.longitude)
lsstObs.elevation = site.height

sm = sb.SkyModel(mags=True)

filterDict = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z': 4, 'y': 5}
indices = np.arange(mjds.size)
loopSize = mjds.size
oldPC = 0
for i, mjd, djd in zip(indices, mjds, mjds - doff):
    lsstObs.date = djd
    sun.compute(lsstObs)
    if sun.alt > sun_alt_limit:
        results['mask'][i] = 0
    else:
        moon.compute(djd)
        moon_mask_indices = healTree.query_ball_point(
            treexyz(moon.ra, moon.dec), moon_avoid)
        venus.compute(djd)
Exemplo n.º 16
0
    diode['y'] = tempy
    diode['z'] = tempz

# Load up LSST filters
throughPath = os.getenv('LSST_THROUGHPUTS_BASELINE')
keys = ['r', 'z', 'y']
nfilt = len(keys)
filters = {}
for filtername in keys:
    bp = np.loadtxt(os.path.join(throughPath, 'filter_' + filtername + '.dat'),
                    dtype=list(zip(['wave', 'trans'], [float] * 2)))
    tempB = Bandpass()
    tempB.setBandpass(bp['wave'], bp['trans'])
    filters[filtername] = tempB

sm = sb.SkyModel(twilight=False, moon=False, zodiacal=False, mags=True)
sm.setRaDecMjd([0.], [np.radians(90.)], 45000., azAlt=True)
sm.computeSpec()
mags = sm.computeMags()
modelFluxLevels = {}
modelFluxLevels['r'] = sm.spec[0][2]
modelFluxLevels['z'] = sm.spec[0][4]
modelFluxLevels['y'] = sm.spec[0][5]

modelMagLevels = {}
modelMagLevels['r'] = mags[0][2]
modelMagLevels['z'] = mags[0][4]
modelMagLevels['y'] = mags[0][5]

# Make some plots
filterNames = ['r', 'z', 'y']
Exemplo n.º 17
0
def recalcmags(j, lst=calcdfs):
    logfname = 'newres_{}.log'.format(j)
    with open(logfname, 'w') as f:
        f.write('starting split {} \n'.format(j))
    # print('starting split ', j)
    df = dfs[j]
    sm = sb.SkyModel(observatory='LSST', mags=False, preciseAltAz=True)
    i = 0
    fieldmags = np.zeros(len(df), dtype=np.float)
    skymags = np.zeros(len(df), dtype=np.float)

    # ditheredmags = np.zeros(len(df), dtype=np.float)
    for obsHistID, row in df.iterrows():
        bandname = row['filter']
        airmass = row['airmass']
        # The Skybrightness Model only has support for airmass <=2.5
        if airmass > 2.5:
            skymags[i] = np.nan
            fieldmags[i] = np.nan
            continue

        # Get atmospheric transmission for airmass of pointing
        fname = atmTransName(airmass)
        atmTrans = np.loadtxt(fname)
        wave, trans = hwbpdict[bandname].multiplyThroughputs(
            atmTrans[:, 0], atmTrans[:, 1])
        bp = Bandpass(wavelen=wave, sb=trans)
        sm.setRaDecMjd(lon=[row['fieldRA']],
                       lat=[row['fieldDec']],
                       filterNames=[row['filter']],
                       mjd=row['expMJD'],
                       degrees=False,
                       azAlt=False)

        wave, spec = sm.returnWaveSpec()
        sed = Sed(wavelen=wave, flambda=spec[0])
        skymags[i] = sm.returnMags(bandpasses=hwbpdict)[row['filter']][0]
        fieldmags[i] = calcM5(sed, bp, hwbpdict[bandname], photparams,
                              row['FWHMeff'])
        #sm.setRaDecMjd(lon=row['ditheredRA'], lat=row['ditheredDec'], filterNames=row['filter'],
        #               mjd=row['expMJD'], degrees=False, azAlt=False)

        # sed = Sed(wavelen=wave, flambda=spec[1])
        # ditheredmags[i] = calcM5(sed, bp, hwbpdict[bandname], photparams,
        #                         row['FWHMeff'])

        i += 1
        if (i % 1000) == 0:
            with open(logfname, mode='a+') as f:
                f.write('calculation done for {} th record\n'.format(i))

    df['fieldm5'] = fieldmags
    df['skymags'] = skymags
    #df['ditheredm5'] = ditheredmags
    lst.append(df)
    # print('done')

    fname = 'newres{}.hdf'.format(j)
    df = df[['fiveSigmaDepth', 'fieldm5', 'skymags', 'airmass', 'filter']]
    with open(logfname, mode='a+') as f:
        f.write('dataframe calculated')
    df.to_hdf(fname, key='0')
    # print('finished writing ', fname)
    # print('num of lines is ', len(df))
    with open(logfname, mode='a+') as f:
        f.write('dataframe written')
    return df
Exemplo n.º 18
0
    names = ['mjd', 'sun_alt']
    for survey in dds:
        names.append(survey.survey_name+'_airmass')
        names.append(survey.survey_name+'_sky_g')
        names.append(survey.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.array([survey.ra for survey in dds])
    decs = np.array([survey.dec for survey in dds])

    sm = sb.SkyModel(observatory='LSST', mags=True)
    mags = []
    airmasses = []
    sun_alts = []

    maxi = mjds.size
    for i, mjd in enumerate(mjds):
        progress = i/maxi*100
        text = "\rprogress = %0.1f%%" % progress
        sys.stdout.write(text)
        sys.stdout.flush()

        sm.setRaDecMjd(ras, decs, mjd, degrees=False)
        if sm.sunAlt > sun_limit:
            mags.append(sm.returnMags()['g']*0)
            airmasses.append(sm.airmass*0)
Exemplo n.º 19
0
import lsst.sims.skybrightness as sb
import healpy as hp
import matplotlib.pylab as plt

plt.rcParams.update({'axes.labelsize': 'x-large'})
plt.rcParams.update({'axes.titlesize': 'x-large'})
plt.rcParams.update({'xtick.labelsize': 'large', 'ytick.labelsize': 'large'})

# Load up the spectra and plot some examples of each component

comps = [
    'twilight', 'zodiacal', 'moon', 'airglow', 'lowerAtm', 'upperAtm',
    'scatteredStar', 'mergedSpec'
]

sm = sb.SkyModel(lowerAtm=True, upperAtm=True, scatteredStar=True)

nside = 8
hpmap = np.zeros(hp.nside2npix(nside))
lat, ra = hp.pix2ang(nside, np.arange(hpmap.size))
dec = np.pi / 2 - lat
sm.setRaDecMjd(ra, dec, 49353.177645, degrees=False, azAlt=True)

# Zodical
for comp in comps:
    setattr(sm, comp, False)
sm.zodiacal = True
sm.interpSky()
#import pdb ; pdb.set_trace()
fig, ax = plt.subplots()
ax.semilogy(sm.wave,
Exemplo n.º 20
0
 def sm_spec2(self):
     cls = type(self)
     if cls._sm_spec2 is None:
         cls._sm_spec2 = sb.SkyModel(mags=False)
     return cls._sm_spec2
Exemplo n.º 21
0
    def addNoiseAndBackground(self,
                              image,
                              bandpass=None,
                              m5=None,
                              FWHMeff=None,
                              photParams=None,
                              chipName=None):
        """
        This method actually adds the sky background and noise to an image.

        Note: default parameters are defined in

        sims_photUtils/python/lsst/sims/photUtils/photometricDefaults.py

        @param [in] image is the GalSim image object to which the background
        and noise are being added.

        @param [in] bandpass is a CatSim bandpass object (not a GalSim bandpass
        object) characterizing the filter through which the image is being taken.

        @param [in] FWHMeff is the FWHMeff in arcseconds

        @param [in] photParams is an instantiation of the
        PhotometricParameters class that carries details about the
        photometric response of the telescope.  Defaults to None.

        @param [in] chipName is the name of the sensor being considered,
        e.g., "R:2,2 S:1,1".

        @param [out] the input image with the background and noise model added to it.
        """
        camera = get_obs_lsstSim_camera()
        center_x, center_y = get_chip_center(chipName, camera)

        # calculate the sky background to be added to each pixel
        skyModel = skybrightness.SkyModel(mags=False)
        ra, dec = lsst.sims.coordUtils.raDecFromPixelCoords(
            xPix=center_x,
            yPix=center_y,
            chipName=chipName,
            camera=camera,
            obs_metadata=self.obs_metadata,
            epoch=2000.0,
            includeDistortion=True)
        mjd = self.obs_metadata.mjd.TAI
        skyModel.setRaDecMjd(ra, dec, mjd, degrees=True)

        bandPassName = self.obs_metadata.bandpass
        bandPassdic = BandpassDict.loadTotalBandpassesFromFiles(
            ['u', 'g', 'r', 'i', 'z', 'y'])

        # Since we are only producing one eimage, account for cases
        # where nsnap > 1 with an effective exposure time for the
        # visit as a whole.  TODO: Undo this change when we write
        # separate images per exposure.
        exposureTime = photParams.nexp * photParams.exptime

        skycounts_persec = SkyCountsPerSec(skyModel, photParams, bandPassdic)
        skyCounts = skycounts_persec(bandPassName) * exposureTime * u.s

        if self.addBackground:
            image += skyCounts

            # if we are adding the skyCounts to the image,there is no need # to pass
            # a skyLevel parameter to the noise model.  skyLevel is # just used to
            # calculate the level of Poisson noise.  If the # sky background is
            # included in the image, the Poisson noise # will be calculated from the
            # actual image brightness.
            skyLevel = 0.0

        else:
            skyLevel = skyCounts * photParams.gain

        if self.addNoise:
            noiseModel = self.getNoiseModel(skyLevel=skyLevel,
                                            photParams=photParams)
            image.addNoise(noiseModel)

        return image
Exemplo n.º 22
0
plt.rcParams.update({'xtick.labelsize': 'large', 'ytick.labelsize': 'large'})

# Let's recreate the delta m_5 plot from figure 3 in:
# http://xxx.lanl.gov/pdf/1510.07574.pdf
telescope = Site('LSST')
nside = 32
lat, ra = hp.pix2ang(nside, np.arange(hp.nside2npix(nside)))
dec = np.pi / 2 - lat

kwargs = dict(twilight=False,
              zodiacal=False,
              moon=True,
              scatteredStar=False,
              mergedSpec=False)

sm = sb.SkyModel(observatory='LSST', mags=True)  # , **kwargs)
mjd = 49353.177645
sm.setRaDecMjd(ra, dec, mjd)
mag = sm.returnMags()
lmst, last = calcLmstLast(mjd, telescope.longitude_rad)

moonRA, moonDec = _raDecFromAltAz(sm.moonAlt, sm.moonAz,
                                  ObservationMetaData(mjd=mjd, site=telescope))

alt, az, pa = _altAzPaFromRaDec(ra, dec,
                                ObservationMetaData(mjd=mjd, site=telescope))
angDist2Moon = np.degrees(haversine(az, alt, sm.moonAz, sm.moonAlt))
ang2 = np.degrees(haversine(ra, dec, moonRA, moonDec))
alt = np.degrees(alt)

mags = -0.5 * (np.nanmin(mag['u']) - mag['u'])
Exemplo n.º 23
0
# Check and see what the model returns for a dark sky at zenith

# Load LSST filters
throughPath = os.getenv('LSST_THROUGHPUTS_BASELINE')
keys = ['u', 'g', 'r', 'i', 'z', 'y']
overview_vals = [22.9, 22.3, 21.2, 20.5, 19.6, 18.6]
filters = {}
for filtername in keys:
    bp = np.loadtxt(os.path.join(throughPath, 'filter_' + filtername + '.dat'),
                    dtype=zip(['wave', 'trans'], [float] * 2))
    tempB = Bandpass()
    tempB.setBandpass(bp['wave'], bp['trans'])
    filters[filtername] = tempB

# XXX--hmm, the zodiacal seems to be fairly important here!
sm = sb.SkyModel(moon=False, twilight=False)  #, zodiacal=False)
sm2 = sb.SkyModel(moon=False, twilight=False, zodiacal=False)
mjd = 56948.05174
sm.setRaDecMjd(np.array([0.]), np.array([90.]), mjd, azAlt=True, degrees=True)
sm2.setRaDecMjd(np.array([0.]), np.array([90.]), mjd, azAlt=True, degrees=True)
sm.computeSpec()
sm2.computeSpec()

print 'filter  ESO model ESO(no Z)  Overview Paper'
for i, key in enumerate(keys):
    print key + '     %.2f &  %.2f  &  %.2f \\\\' % (sm.computeMags(
        filters[key])[0], sm2.computeMags(filters[key])[0], overview_vals[i])

# Let's also output the cannon filters while we're at it:
canonFilters = {}
fnames = ['blue_canon.csv', 'green_canon.csv', 'red_canon.csv']
Exemplo n.º 24
0
    def addNoiseAndBackground(self,
                              image,
                              bandpass=None,
                              m5=None,
                              FWHMeff=None,
                              photParams=None):
        """
        This method actually adds the sky background and noise to an image.

        Note: default parameters are defined in

        sims_photUtils/python/lsst/sims/photUtils/photometricDefaults.py

        @param [in] image is the GalSim image object to which the background
        and noise are being added.

        @param [in] bandpass is a CatSim bandpass object (not a GalSim bandpass
        object) characterizing the filter through which the image is being taken.

        @param [in] FWHMeff is the FWHMeff in arcseconds

        @param [in] photParams is an instantiation of the
        PhotometricParameters class that carries details about the
        photometric response of the telescope.  Defaults to None.

        @param [out] the input image with the background and noise model added to it.
        """

        # calculate the sky background to be added to each pixel
        skyModel = skybrightness.SkyModel(mags=True)
        ra = np.array([self.obs_metadata.pointingRA])
        dec = np.array([self.obs_metadata.pointingDec])
        mjd = self.obs_metadata.mjd.TAI
        skyModel.setRaDecMjd(ra, dec, mjd, degrees=True)

        bandPassName = self.obs_metadata.bandpass
        skyMagnitude = skyModel.returnMags()[bandPassName]

        # Since we are only producing one eimage, account for cases
        # where nsnap > 1 with an effective exposure time for the
        # visit as a whole.  TODO: Undo this change when we write
        # separate images per exposure.
        exposureTime = photParams.nexp * photParams.exptime * u.s

        skyCounts = skyCountsPerSec(surface_brightness=skyMagnitude,
                                    filter_band=bandPassName) * exposureTime

        # print "Magnitude:", skyMagnitude
        # print "Brightness:", skyMagnitude, skyCounts

        image = image.copy()

        if self.addBackground:
            image += skyCounts

            # if we are adding the skyCounts to the image,there is no need # to pass
            # a skyLevel parameter to the noise model.  skyLevel is # just used to
            # calculate the level of Poisson noise.  If the # sky background is
            # included in the image, the Poisson noise # will be calculated from the
            # actual image brightness.
            skyLevel = 0.0

        else:
            skyLevel = skyCounts * photParams.gain

        if self.addNoise:
            noiseModel = self.getNoiseModel(skyLevel=skyLevel,
                                            photParams=photParams)
            image.addNoise(noiseModel)

        return image
 def setUpClass(self):
     # Load up the spectra just once to speed things up a bit
     self.sm_mags = sb.SkyModel(mags=True)
     self.sm_mags2 = sb.SkyModel(mags=True)
     self.sm_spec = sb.SkyModel(mags=False)
     self.sm_spec2 = sb.SkyModel(mags=False)
def gen_cloud_maps():
    sm = sb.SkyModel(mags=True)
    hpindx = np.arange(hp.nside2npix(32))
    ra, dec = utils._hpid2RaDec(32, hpindx)

    do_query = False
    dbAddress = 'sqlite:///meddata.sqlite'
    engine = sqla.create_engine(dbAddress)
    connection = engine.raw_connection()
    cursor = connection.cursor()

    # Check all the mjd values in the db
    if do_query:
        query = 'select distinct(mjd) from medskybrightness;'
        cursor.execute(query)
        data = cursor.fetchall()
        mjd_clean = [ack[0] for ack in data]
        mjd_clean = np.array(mjd_clean)

    # Let's go 57200 as a start
    mjd_start = 57200
    mjd_length = 40.

    query = 'select distinct(mjd) from medskybrightness where mjd > %f and mjd < %f;' % (
        mjd_start, mjd_start + mjd_length)

    cursor.execute(query)
    data = cursor.fetchall()
    mjd_clean = np.array([ack[0] for ack in data])

    cloud_maps = []
    mjd_final = []

    moon_limit = np.radians(30.)
    am_limit = 2.5

    maxI = mjd_clean[1:].size
    for i, mjd in enumerate(mjd_clean[1:]):
        if (mjd_clean[i] - mjd_clean[i - 1]) < (2. / 60. / 24.):
            sf = single_frame(mjd_clean[i - 1])
            sf2 = single_frame(mjd_clean[i])
            if (sf.max() != hp.UNSEEN) & (sf2.max() != hp.UNSEEN):
                diff = (sf - sf2) / sf
                mask = np.where((sf == hp.UNSEEN) | (sf2 == hp.UNSEEN))
                diff[mask] = hp.UNSEEN
                if diff.max() != hp.UNSEEN:
                    cf, cloud_mask = cloudyness(diff, skyRMS_max=0.05)
                    sm.setRaDecMjd(ra, dec, mjd)
                    skymap = sm.returnMags()['r']
                    mask = np.where((skymap == hp.UNSEEN)
                                    | np.isnan(skymap))[0]
                    cloud_mask[mask] = 2
                    moon_dist = utils.haversine(ra, dec, sm.moonRA, sm.moonDec)
                    mask = np.where((moon_dist < moon_limit)
                                    | (sm.airmass < 1.)
                                    | (sm.airmass > am_limit))
                    cloud_mask[mask] = 2
                    cloud_maps.append(cloud_mask)
                    # put in some masking near the moon
                    mjd_final.append(mjd)

                    progress = i / float(maxI) * 100
                    text = "\r progress = %.1f%%" % progress
                    sys.stdout.write(text)
                    sys.stdout.flush()

    cloud_maps = np.array(cloud_maps)
    map_key = {
        'good': 0,
        'masked': 2,
        'bright_in_current': -1,
        'bright_in_last': 1
    }
    np.savez('month_o_clouds.npz',
             cloud_maps=cloud_maps,
             mjds=mjd_final,
             map_key=map_key)
Exemplo n.º 27
0
    callList = [
        'ffmpeg', '-i',
        os.path.join(outDir, '%s_%%04d.png' % (outfileroot)), '-vf',
        'scale=%s:%s' % (str(320), str(-1)), '-t',
        str(10), '-r',
        str(10),
        os.path.join(outDir,
                     '%s_%s_%s.gif' % (outfileroot, str(ips), str(fps)))
    ]
    print 'converting to animated gif with:'
    print ' '.join(callList)
    p2 = subprocess.check_call(callList)


telescope = TelescopeInfo('LSST')
sm = sb.SkyModel()

# Let's load up a pile of data and make a movie

canonDict = {}
canonFiles = {
    'R': 'red_canon.csv',
    'G': 'green_canon.csv',
    'B': 'blue_canon.csv'
}

path = os.path.join(os.environ.get('SIMS_SKYBRIGHTNESS_DATA_DIR'), 'Canon')
for key in canonFiles.keys():
    data = np.loadtxt(os.path.join(path, canonFiles[key]),
                      delimiter=',',
                      dtype=zip(['wave', 'throughput'], [float, float]))
Exemplo n.º 28
0
dateData, mjd = sb.allSkyDB(2744,
                            sqlQ=sqlQ,
                            filt=None,
                            dtypes=zip(['dateID', 'mjd', 'sunAlt', 'moonAlt'],
                                       [int, float, float, float]))

skipsize = 10
indices = np.arange(0, dateData.size, skipsize)

# Maybe bin things on 15-min timescales to cut down the number of calls I need to make to the model
#binsize = 15./60./24.
#edges = np.arange(skydata['mjd'].min(),skydata['mjd'].max()+binsize*2, binsize)

read = True
filters = ['R', 'G', 'B']
sm = sb.SkyModel(mags=False)
telescope = TelescopeInfo('LSST')

nside = 16
# Demand this many stars before trying to fit. This should reject the very cloudy frames
starLimit = 200

# Create array to hold the results of
names = [
    'moonAlt', 'sunAlt', 'obsZenith', 'modelZenith', 'obsDarkestHP',
    'modelDarkestHP', 'obsBrightestHP', 'modelBrightestHP', 'obsPointing',
    'modelPointing', 'angDistancesFaint', 'angDistancesBright', 'frameZP',
    'mjd'
]

# I guess I might as well add the brightest points in the sky as well...
Exemplo n.º 29
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)
Exemplo n.º 30
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)