Exemplo n.º 1
0
    def loadTotalBandpassesFromFiles(cls,
                                    bandpassNames=['u', 'g', 'r', 'i', 'z', 'y'],
                                    bandpassDir = os.path.join(getPackageDir('throughputs'),'baseline'),
                                    bandpassRoot = 'total_'):
        """
        This will take the list of band passes named by bandpassNames and load them into
        a BandpassDict

        The bandpasses loaded this way are total bandpasses: they account for instrumental
        and atmospheric transmission.

        @param [in] bandpassNames is a list of names identifying each filter.
        Defaults to ['u', 'g', 'r', 'i', 'z', 'y']

        @param [in] bandpassDir is the name of the directory where the bandpass files are stored

        @param [in] bandpassRoot contains the first part of the bandpass file name, i.e., it is assumed
        that the bandpasses are stored in files of the type

        bandpassDir/bandpassRoot_bandpassNames[i].dat

        if we want to load bandpasses for a telescope other than LSST, we would do so
        by altering bandpassDir and bandpassRoot

        @param [out] bandpassDict is a BandpassDict containing the loaded throughputs
        """

        bandpassList = []

        for w in bandpassNames:
            bandpassDummy = Bandpass()
            bandpassDummy.readThroughput(os.path.join(bandpassDir,"%s.dat" % (bandpassRoot + w)))
            bandpassList.append(bandpassDummy)

        return cls(bandpassList, bandpassNames)
Exemplo n.º 2
0
def buildVendorDetector(vendorDir, addLosses=True):
    """
    Builds a detector response from the files in vendorDir, by reading the *_QE.dat
      and *_Losses subdirectory for a single version of the detector.
    Returns a Bandpass object.
    If addLosses is True, the QE curve is multiplied by the losses in the *Losses.dat files.
    If addLosses is False, the QE curve does not have any losses included.
    """
    # Read the QE file.
    qefile = glob(os.path.join(vendorDir, '*_QE.dat'))
    if len(qefile) != 1:
        raise ValueError('Expected a single QE file in this directory, found: ', qefile)
    qefile = qefile[0]
    qe = Bandpass()
    qe.readThroughput(qefile)
    if addLosses:
        loss = _readLosses(vendorDir)
        wavelength, sb = qe.multiplyThroughputs(loss.wavelen, loss.sb)
        qe.setBandpass(wavelength, sb)
    # Verify that no values go significantly below zero.
    belowzero = np.where(qe.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if qe.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in QE response significantly below zero.')
    # If they are just small errors in interpolation, set to zero.
    qe.sb[belowzero] = 0
    return qe
def buildVendorDetector(vendorDir, addLosses=True):
    """
    Builds a detector response from the files in vendorDir, by reading the *_QE.dat
      and *_Losses subdirectory for a single version of the detector.
    Returns a Bandpass object.
    If addLosses is True, the QE curve is multiplied by the losses in the *Losses.dat files.
    If addLosses is False, the QE curve does not have any losses included.
    """
    # Read the QE file.
    qefile = glob(os.path.join(vendorDir, '*_QE.dat'))
    if len(qefile) != 1:
        raise ValueError('Expected a single QE file in this directory, found: ', qefile)
    qefile = qefile[0]
    qe = Bandpass()
    qe.readThroughput(qefile)
    if addLosses:
        loss = _readLosses(vendorDir)
        wavelength, sb = qe.multiplyThroughputs(loss.wavelen, loss.sb)
        qe.setBandpass(wavelength, sb)
    # Verify that no values go significantly below zero.
    belowzero = np.where(qe.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if qe.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in QE response significantly below zero.')
    # If they are just small errors in interpolation, set to zero.
    qe.sb[belowzero] = 0
    return qe
def buildMirror(mirrorDir, addLosses=True):
    """
    Build a mirror throughput curve.
    Assumes there are *Losses.dat subdirectory with loss files
       and a m*_Ideal.dat file with the mirror throughput.
    Returns a bandpass object.
    If addLosses is True, the *_Ideal.dat file is multiplied by the *_Losses/*.dat files.
    """
    # Read the mirror reflectance curve.
    mirrorfile = glob(os.path.join(mirrorDir, 'm*Ideal.dat'))
    if len(mirrorfile) != 1:
        raise ValueError('Expected a single mirror file in directory %s, found: ' %mirrorDir, mirrorfile)
    mirrorfile = mirrorfile[0]
    mirror = Bandpass()
    mirror.readThroughput(mirrorfile)
    if addLosses:
        loss = _readLosses(mirrorDir)
        wavelen, sb = mirror.multiplyThroughputs(loss.wavelen, loss.sb)
        mirror.setBandpass(wavelen, sb)
    # Verify that no values go significantly below zero.
    belowzero = np.where(mirror.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if mirror.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in mirror response significantly below zero')
    # If they are just small errors in interpolation, set to zero.
    mirror.sb[belowzero] = 0
    return mirror
Exemplo n.º 5
0
    def setUp(self):

        starFileName = os.path.join(lsst.utils.getPackageDir("sims_sed_library"), "starSED")
        starFileName = os.path.join(starFileName, "kurucz", "km20_5750.fits_g40_5790.gz")
        starName = os.path.join(lsst.utils.getPackageDir("sims_sed_library"), starFileName)
        self.starSED = Sed()
        self.starSED.readSED_flambda(starName)
        imsimband = Bandpass()
        imsimband.imsimBandpass()
        fNorm = self.starSED.calcFluxNorm(22.0, imsimband)
        self.starSED.multiplyFluxNorm(fNorm)

        hardwareDir = os.path.join(lsst.utils.getPackageDir("throughputs"), "baseline")
        componentList = ["detector.dat", "m1.dat", "m2.dat", "m3.dat", "lens1.dat", "lens2.dat", "lens3.dat"]
        self.skySed = Sed()
        self.skySed.readSED_flambda(os.path.join(hardwareDir, "darksky.dat"))

        totalNameList = ["total_u.dat", "total_g.dat", "total_r.dat", "total_i.dat", "total_z.dat", "total_y.dat"]

        self.bpList = []
        self.hardwareList = []
        for name in totalNameList:
            dummy = Bandpass()
            dummy.readThroughput(os.path.join(hardwareDir, name))
            self.bpList.append(dummy)

            dummy = Bandpass()
            hardwareNameList = [os.path.join(hardwareDir, name)]
            for component in componentList:
                hardwareNameList.append(os.path.join(hardwareDir, component))
            dummy.readThroughputList(hardwareNameList)
            self.hardwareList.append(dummy)

        self.filterNameList = ["u", "g", "r", "i", "z", "y"]
Exemplo n.º 6
0
    def testLoadTotalBandpassesFromFiles(self):
        """
        Test that the class method loadTotalBandpassesFromFiles produces the
        expected result
        """

        bandpassDir = os.path.join(getPackageDir('sims_photUtils'), 'tests', 'cartoonSedTestData')
        bandpassNames = ['g', 'r', 'u']
        bandpassRoot = 'test_bandpass_'

        bandpassDict = BandpassDict.loadTotalBandpassesFromFiles(bandpassNames=bandpassNames,
                                                                 bandpassDir=bandpassDir,
                                                                 bandpassRoot = bandpassRoot)

        controlBandpassList = []
        for bpn in bandpassNames:
            dummyBp = Bandpass()
            dummyBp.readThroughput(os.path.join(bandpassDir,bandpassRoot+bpn+'.dat'))
            controlBandpassList.append(dummyBp)

        wMin = controlBandpassList[0].wavelen[0]
        wMax = controlBandpassList[0].wavelen[-1]
        wStep = controlBandpassList[0].wavelen[1]-controlBandpassList[0].wavelen[0]

        for bp in controlBandpassList:
            bp.resampleBandpass(wavelen_min=wMin, wavelen_max=wMax, wavelen_step=wStep)

        for test, control in zip(bandpassDict.values(), controlBandpassList):
            numpy.testing.assert_array_almost_equal(test.wavelen, control.wavelen, 19)
            numpy.testing.assert_array_almost_equal(test.sb, control.sb, 19)
    def testLoadTotalBandpassesFromFiles(self):
        """
        Test that the class method loadTotalBandpassesFromFiles produces the
        expected result
        """

        bandpassDir = os.path.join(getPackageDir('sims_photUtils'), 'tests', 'cartoonSedTestData')
        bandpassNames = ['g', 'r', 'u']
        bandpassRoot = 'test_bandpass_'

        bandpassDict = BandpassDict.loadTotalBandpassesFromFiles(bandpassNames=bandpassNames,
                                                                 bandpassDir=bandpassDir,
                                                                 bandpassRoot = bandpassRoot)

        controlBandpassList = []
        for bpn in bandpassNames:
            dummyBp = Bandpass()
            dummyBp.readThroughput(os.path.join(bandpassDir,bandpassRoot+bpn+'.dat'))
            controlBandpassList.append(dummyBp)

        wMin = controlBandpassList[0].wavelen[0]
        wMax = controlBandpassList[0].wavelen[-1]
        wStep = controlBandpassList[0].wavelen[1]-controlBandpassList[0].wavelen[0]

        for bp in controlBandpassList:
            bp.resampleBandpass(wavelen_min=wMin, wavelen_max=wMax, wavelen_step=wStep)

        for test, control in zip(bandpassDict.values(), controlBandpassList):
            numpy.testing.assert_array_almost_equal(test.wavelen, control.wavelen, 19)
            numpy.testing.assert_array_almost_equal(test.sb, control.sb, 19)
Exemplo n.º 8
0
def buildMirror(mirrorDir, addLosses=True):
    """
    Build a mirror throughput curve.
    Assumes there are *Losses.dat subdirectory with loss files
       and a m*_Ideal.dat file with the mirror throughput.
    Returns a bandpass object.
    If addLosses is True, the *_Ideal.dat file is multiplied by the *_Losses/*.dat files.
    """
    # Read the mirror reflectance curve.
    mirrorfile = glob(os.path.join(mirrorDir, 'm*Ideal.dat'))
    if len(mirrorfile) != 1:
        raise ValueError('Expected a single mirror file in directory %s, found: ' %mirrorDir, mirrorfile)
    mirrorfile = mirrorfile[0]
    mirror = Bandpass()
    mirror.readThroughput(mirrorfile)
    if addLosses:
        loss = _readLosses(mirrorDir)
        wavelen, sb = mirror.multiplyThroughputs(loss.wavelen, loss.sb)
        mirror.setBandpass(wavelen, sb)
    # Verify that no values go significantly below zero.
    belowzero = np.where(mirror.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if mirror.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in mirror response significantly below zero')
    # If they are just small errors in interpolation, set to zero.
    mirror.sb[belowzero] = 0
    return mirror
Exemplo n.º 9
0
    def Load_Atmosphere(self, airmass=1.2):

        self.airmass = airmass
        atmosphere = Bandpass()
        atmosphere.readThroughput(
            os.path.join(self.atmosDir, 'atmos_%d.dat' % (self.airmass * 10)))
        self.atmos = Bandpass(wavelen=atmosphere.wavelen, sb=atmosphere.sb)

        for f in self.filterlist:
            wavelen, sb = self.lsst_system[f].multiplyThroughputs(
                atmosphere.wavelen, atmosphere.sb)
            self.lsst_atmos[f] = Bandpass(wavelen=wavelen, sb=sb)

        if self.aerosol:
            atmosphere_aero = Bandpass()
            atmosphere_aero.readThroughput(
                os.path.join(self.atmosDir,
                             'atmos_%d_aerosol.dat' % (self.airmass * 10)))
            self.atmos_aerosol = Bandpass(wavelen=atmosphere_aero.wavelen,
                                          sb=atmosphere_aero.sb)

            for f in self.filterlist:
                wavelen, sb = self.lsst_system[f].multiplyThroughputs(
                    atmosphere_aero.wavelen, atmosphere_aero.sb)
                self.lsst_atmos_aerosol[f] = Bandpass(wavelen=wavelen, sb=sb)
Exemplo n.º 10
0
def getHscThroughput(f):
    if f not in ["Y"]:
        raise ValueError("HSC does not have a {} filter".format(f))
    throughputsDir = "HSC_throughputs"
    throughputsFile = os.path.join(throughputsDir, "total_{}.dat".format(f))
    hscBand = Bandpass()
    hscBand.readThroughput(throughputsFile)
    return hscBand
Exemplo n.º 11
0
def getUkidssThroughput(f):
    if f not in ["Z", "Y", "H", "J", "K"]:
        raise ValueError("UKIDSS does not have a {} filter".format(f))
    throughputsDir = "UKIDSS_throughputs"
    throughputsFile = os.path.join(throughputsDir, "total_{}.dat".format(f))
    ukidssBand = Bandpass()
    ukidssBand.readThroughput(throughputsFile)
    return ukidssBand
Exemplo n.º 12
0
def getDesThroughput(f):
    if f not in ["u", "g", "r", "i", "z", "y"]:
        raise ValueError("DES does not have a {} filter".format(f))
    throughputsDir = "DES_throughputs"
    throughputsFile = os.path.join(throughputsDir, "total_{}.dat".format(f))
    desBand = Bandpass()
    desBand.readThroughput(throughputsFile)
    return desBand
Exemplo n.º 13
0
def fit_invsnr(mags, floor, m5, bandpass_name='r'):
    filterdir = os.getenv('LSST_THROUGHPUTS_BASELINE')
    bandpass = Bandpass()
    bandpass.readThroughput(os.path.join(filterdir, 'total_%s.dat'%bandpass_name))
    invsnr_arr = []
    for mag in mags:
        snr = flat_sed_snr(mag, bandpass, m5)
        invsnr_arr.append(math.hypot(1./snr, floor))
    return invsnr_arr
Exemplo n.º 14
0
def getPanstarrsThroughput(f):
    if f not in ["g", "r", "i", "z", "y"]:
        raise ValueError("PanSTARRS does not have a {} filter".format(f))
    # the PanStarrs throughputs are in a subdirectory panStarrs, not baseline
    throughputsDir = os.getenv("LSST_THROUGHPUTS_BASELINE")
    throughputsFile = os.path.join(throughputsDir, "..", "panStarrs",
                                   "panStarrs_{}.dat".format(f))
    panstarrsBand = Bandpass()
    panstarrsBand.readThroughput(throughputsFile)
    return panstarrsBand
Exemplo n.º 15
0
def read_stdatmo(override_filename = None):
    # read the standard atmosphere bandpass file, precomputed by MODTRAN & DaveBurke.
    # this is closely equivalent to atmos_12.dat
    atmosdir = os.getenv("LSST_THROUGHPUTS_ATMOS")
    atmos_bp = Bandpass()
    if override_filename == None:
        atmos_bp.readThroughput(os.path.join(atmosdir, "atmos_std.dat"))
    else:
        atmos_bp.readThroughput(os.path.join(atmosdir, override_filename))
    return atmos_bp
Exemplo n.º 16
0
def getVistaThroughput(f):
    if f not in ['Y', 'J', 'H', 'K']:
        raise ValueError("VISTA does not have a {} filter".format(f))

    throughputsDir = "VISTA_throughputs"
    throughputsFile = os.path.join(throughputsDir,
                                   'VISTA_{}_total.dat'.format(f))
    vistaBand = Bandpass()
    vistaBand.readThroughput(throughputsFile)
    return vistaBand
Exemplo n.º 17
0
    def testNoise(self):
        """
        Test that ExampleCCDNoise puts the expected counts on an image
        by generating a flat image, adding noise and background to it,
        and calculating the variance of counts in the image.
        """

        lsstDefaults = LSSTdefaults()
        gain = 2.5
        readnoise = 6.0
        photParams = PhotometricParameters(gain=gain, readnoise=readnoise)
        img = galsim.Image(100, 100)
        noise = ExampleCCDNoise(seed=42)
        m5 = 24.5
        bandpass = Bandpass()
        bandpass.readThroughput(
            os.path.join(getPackageDir('throughputs'), 'baseline',
                         'total_r.dat'))
        background = calcSkyCountsPerPixelForM5(
            m5,
            bandpass,
            FWHMeff=lsstDefaults.FWHMeff('r'),
            photParams=photParams)

        noisyImage = noise.addNoiseAndBackground(
            img,
            bandpass,
            m5=m5,
            FWHMeff=lsstDefaults.FWHMeff('r'),
            photParams=photParams)

        mean = 0.0
        var = 0.0
        for ix in range(1, 101):
            for iy in range(1, 101):
                mean += noisyImage(ix, iy)

        mean = mean / 10000.0

        for ix in range(1, 101):
            for iy in range(1, 101):
                var += (noisyImage(ix, iy) - mean) * (noisyImage(ix, iy) -
                                                      mean)

        var = var / 9999.0

        varElectrons = background * gain + readnoise
        varADU = varElectrons / (gain * gain)

        msg = 'background %e mean %e ' % (background, mean)
        self.assertLess(np.abs(background / mean - 1.0), 0.05, msg=msg)

        msg = 'var %e varADU %e ; ratio %e ; background %e' % (
            var, varADU, var / varADU, background)
        self.assertLess(np.abs(var / varADU - 1.0), 0.05, msg=msg)
Exemplo n.º 18
0
def getSdssThroughput(f):
    if f not in ["u", "g", "r", "i", "z"]:
        raise ValueError("SDSS does not have a {} filter".format(f))
    # the SDSS throughputs are in a subdirectory sdss, not baseline
    throughputsDir = os.getenv("LSST_THROUGHPUTS_BASELINE")
    # doi use the Doi et al. 2010 throughput curves
    throughputsFile = os.path.join(throughputsDir, "..", "sdss",
                                   "doi_{}.dat".format(f))
    sdssBand = Bandpass()
    sdssBand.readThroughput(throughputsFile)
    return sdssBand
Exemplo n.º 19
0
def getLsstThroughput(f):
    if f not in ["u", "g", "r", "i", "z", "y"]:
        raise ValueError("LSST does not have a {} filter".format(f))
    # Get the throughputs directory using the 'throughputs' package env variables.
    throughputsDir = os.getenv('LSST_THROUGHPUTS_BASELINE')
    throughputsFile = os.path.join(throughputsDir, 'total_{}.dat'.format(f))

    # read the throughputs file into lsstBand
    lsstBand = Bandpass()
    lsstBand.readThroughput(throughputsFile)
    return lsstBand
    def setUpClass(cls):
        lsstDefaults=LSSTdefaults()
        cls.dbName = 'uncertaintyTestDB.db'
        if os.path.exists(cls.dbName):
            os.unlink(cls.dbName)

        default_obs_metadata = makePhoSimTestDB(filename=cls.dbName, size=10, radius = 5.0)
        bandpass = ['u', 'g', 'r', 'i', 'z', 'y']
        m5 = lsstDefaults._m5.values()

        cls.obs_metadata = ObservationMetaData(
                                              pointingRA = default_obs_metadata.pointingRA,
                                              pointingDec = default_obs_metadata.pointingDec,
                                              rotSkyPos = default_obs_metadata.rotSkyPos,
                                              bandpassName = bandpass,
                                              m5 = m5
                                              )

        cls.obs_metadata.setBandpassM5andSeeing(bandpassName=bandpass, m5=m5)
        cls.driver = 'sqlite'
        cls.host = ''

        cls.skySeds = []
        cls.hardwareBandpasses = []
        cls.totalBandpasses = []
        cls.bandpasses = ['u', 'g', 'r', 'i', 'z', 'y']

        components = ['detector.dat', 'm1.dat', 'm2.dat', 'm3.dat',
                      'lens1.dat', 'lens2.dat', 'lens3.dat']

        for b in cls.bandpasses:
            bandpassDummy = Bandpass()
            bandpassDummy.readThroughput(os.path.join(lsst.utils.getPackageDir('throughputs'),
                                                      'baseline', 'total_%s.dat' % b))
            cls.totalBandpasses.append(bandpassDummy)

        for b in cls.bandpasses:
            finalComponents = []
            for c in components:
                finalComponents.append(os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline', c))
            finalComponents.append(os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline', 'filter_%s.dat' %b))
            bandpassDummy = Bandpass()
            bandpassDummy.readThroughputList(finalComponents)
            cls.hardwareBandpasses.append(bandpassDummy)

        for i in range(len(cls.bandpasses)):
            sedDummy = Sed()
            sedDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline', 'darksky.dat'))
            normalizedSedDummy = setM5(cls.obs_metadata.m5[cls.bandpasses[i]], sedDummy,
                                       cls.totalBandpasses[i], cls.hardwareBandpasses[i],
                                       FWHMeff=lsstDefaults.FWHMeff(cls.bandpasses[i]),
                                       photParams=PhotometricParameters())

            cls.skySeds.append(normalizedSedDummy)
Exemplo n.º 21
0
    def getFilesAndBandpasses(
        self,
        catalog,
        nameRoot=None,
        bandpassDir=os.path.join(getPackageDir('throughputs'), 'baseline'),
        bandpassRoot='total_',
    ):
        """
        Take a GalSimCatalog.  Return a list of fits files and and OrderedDict of bandpasses associated
        with that catalog

        @param [in] catalog is a GalSimCatalog instantiation

        @param [in] nameRoot is the nameRoot prepended to the fits files output by that catalog

        @param[in] bandpassDir is the directory where bandpass files can be found

        @param [in] bandpassRoot is the root of the name of the bandpass files

        @param [out] listOfFiles is a list of the names of the fits files written by this catalog

        @param [out] bandpassDict is an OrderedDict of Bandpass instantiations corresponding to the
        filters in this catalog.
        """

        # write the fits files
        catalog.write_images(nameRoot=nameRoot)

        # a list of bandpasses over which we are integraging
        listOfFilters = []
        listOfFiles = []

        # read in the names of all of the written fits files directly from the
        # InstanceCatalog's GalSimInterpreter
        # Use AFW to read in the FITS files and calculate the ADU
        for name in catalog.galSimInterpreter.detectorImages:
            if nameRoot is not None:
                name = nameRoot + '_' + name

            listOfFiles.append(name)

            if name[-6] not in listOfFilters:
                listOfFilters.append(name[-6])

        bandpassDict = OrderedDict()
        for filterName in listOfFilters:
            bandpassName = os.path.join(bandpassDir,
                                        bandpassRoot + filterName + '.dat')
            bandpass = Bandpass()
            bandpass.readThroughput(bandpassName)
            bandpassDict[filterName] = bandpass

        return listOfFiles, bandpassDict
    def getFilesAndBandpasses(
        self,
        catalog,
        nameRoot=None,
        bandpassDir=os.path.join(lsst.utils.getPackageDir("throughputs"), "baseline"),
        bandpassRoot="total_",
    ):

        """
        Take a GalSimCatalog.  Return a list of fits files and and OrderedDict of bandpasses associated
        with that catalog

        @param [in] catalog is a GalSimCatalog instantiation

        @param [in] nameRoot is the nameRoot prepended to the fits files output by that catalog

        @param[in] bandpassDir is the directory where bandpass files can be found

        @param [in] bandpassRoot is the root of the name of the bandpass files

        @param [out] listOfFiles is a list of the names of the fits files written by this catalog

        @param [out] bandpassDict is an OrderedDict of Bandpass instantiations corresponding to the
        filters in this catalog.
        """

        # write the fits files
        catalog.write_images(nameRoot=nameRoot)

        # a list of bandpasses over which we are integraging
        listOfFilters = []
        listOfFiles = []

        # read in the names of all of the written fits files directly from the
        # InstanceCatalog's GalSimInterpreter
        # Use AFW to read in the FITS files and calculate the ADU
        for name in catalog.galSimInterpreter.detectorImages:
            if nameRoot is not None:
                name = nameRoot + "_" + name

            listOfFiles.append(name)

            if name[-6] not in listOfFilters:
                listOfFilters.append(name[-6])

        bandpassDict = OrderedDict()
        for filterName in listOfFilters:
            bandpassName = os.path.join(bandpassDir, bandpassRoot + filterName + ".dat")
            bandpass = Bandpass()
            bandpass.readThroughput(bandpassName)
            bandpassDict[filterName] = bandpass

        return listOfFiles, bandpassDict
Exemplo n.º 23
0
def make_invsnr_arr(mag_bright=16., mag_dim=27., mag_delta=0.1, floor=0.02, m5=24.5):
    filterdir = os.getenv('LSST_THROUGHPUTS_BASELINE')
    bandpass = Bandpass()
    bandpass.readThroughput(os.path.join(filterdir, 'total_r.dat'))
    mag = mag_bright
    mag_arr = []
    invsnr_arr = []
    while mag < mag_dim:
        snr = flat_sed_snr(mag, bandpass, m5)
        mag_arr.append(mag)
        invsnr_arr.append(math.hypot(1./snr, floor))
        mag += mag_delta
    return mag_arr, invsnr_arr
Exemplo n.º 24
0
def make_invsnr_arr(mag_bright=16., mag_dim=27., mag_delta=0.1, floor=0.02, m5=24.5):
    filterdir = os.getenv('LSST_THROUGHPUTS_BASELINE')
    bandpass = Bandpass()
    bandpass.readThroughput(os.path.join(filterdir, 'total_r.dat'))
    mag = mag_bright
    mag_arr = []
    invsnr_arr = []
    while mag < mag_dim:
        snr = flat_sed_snr(mag, bandpass, m5)
        mag_arr.append(mag)
        invsnr_arr.append(math.hypot(1./snr, floor))
        mag += mag_delta
    return mag_arr, invsnr_arr
Exemplo n.º 25
0
def getVistaThroughput(f):
    availableFilters = ['Y', 'J', 'H', 'Ks']
    if f not in availableFilters:
        raise ValueError("VISTA does not have a {} filter".format(f) +
                         "Available filters are " + ",".join(availableFilters))

    throughputsDir = "VISTA_throughputs"
    throughputsFile = os.path.join(throughputsDir, 'total_{}.dat'.format(f))
    vistaBand = Bandpass()
    vistaBand.readThroughput(throughputsFile,
                             wavelen_min=500.0,
                             wavelen_max=2500.0,
                             wavelen_step=0.5)

    return vistaBand
Exemplo n.º 26
0
    def Get_Atmosphere(self, airmass=1.2):

        if airmass > 0:
            atmosphere = Bandpass()

        path_atmos = os.path.join(self.atmosDir,
                                  'atmos_%d.dat' % (airmass * 10))

        if os.path.exists(path_atmos):
            atmosphere.readThroughput(
                os.path.join(self.atmosDir, 'atmos_%d.dat' % (airmass * 10)))
        else:
            atmosphere.readThroughput(os.path.join(self.atmosDir, 'atmos.dat'))

        return atmosphere.wavelen, atmosphere.sb
def readAtmosphere(atmosDir, atmosFile='pachonModtranAtm_12.dat'):
    """
    Read an atmosphere throughput curve, from the default location 'atmosDir'
     and default filename 'pachonModtranAtm_12.dat'
    Returns a bandpass object.
    """
    atmofile = os.path.join(atmosDir, atmosFile)
    atmo = Bandpass()
    atmo.readThroughput(atmofile)
    # Verify that no values go significantly below zero.
    belowzero = np.where(atmo.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if atmo.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in atmospheric transmission significantly below zero')
    # If they are just small errors in interpolation, set to zero.
    atmo.sb[belowzero] = 0
    return atmo
Exemplo n.º 28
0
def readAtmosphere(atmosDir, atmosFile='pachonModtranAtm_12.dat'):
    """
    Read an atmosphere throughput curve, from the default location 'atmosDir'
     and default filename 'pachonModtranAtm_12.dat'
    Returns a bandpass object.
    """
    atmofile = os.path.join(atmosDir, atmosFile)
    atmo = Bandpass()
    atmo.readThroughput(atmofile)
    # Verify that no values go significantly below zero.
    belowzero = np.where(atmo.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if atmo.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in atmospheric transmission significantly below zero')
    # If they are just small errors in interpolation, set to zero.
    atmo.sb[belowzero] = 0
    return atmo
Exemplo n.º 29
0
def calcColors(sedname='C.dat'):
    # Calculate SSO colors.
    filterdir = os.getenv('LSST_THROUGHPUTS_BASELINE')
    filterlist = ('u', 'g', 'r', 'i', 'z', 'y')
    lsst ={}
    for f in filterlist:
        lsst[f] = Bandpass()
        lsst[f].readThroughput(os.path.join(filterdir, 'total_'+f+'.dat'))
    vband = Bandpass()
    vband.readThroughput('harris_V.dat')
    csed = Sed()
    csed.readSED_flambda(sedname)
    vmag = csed.calcMag(vband)
    dmags = {}
    for f in filterlist:
        dmags[f] = csed.calcMag(lsst[f]) - vmag
    return dmags
    def testNoise(self):
        """
        Test that ExampleCCDNoise puts the expected counts on an image
        by generating a flat image, adding noise and background to it,
        and calculating the variance of counts in the image.
        """

        lsstDefaults = LSSTdefaults()
        gain = 2.5
        readnoise = 6.0
        photParams=PhotometricParameters(gain=gain, readnoise=readnoise)
        img = galsim.Image(100,100)
        noise = ExampleCCDNoise(seed=42)
        m5 = 24.5
        bandpass = Bandpass()
        bandpass.readThroughput(os.path.join(lsst.utils.getPackageDir('throughputs'),'baseline','total_r.dat'))
        background = calcSkyCountsPerPixelForM5(m5, bandpass, seeing=lsstDefaults.seeing('r'),
                                            photParams=photParams)

        noisyImage = noise.addNoiseAndBackground(img, bandpass, m5=m5,
                                                 seeing=lsstDefaults.seeing('r'),
                                                 photParams=photParams)

        mean = 0.0
        var = 0.0
        for ix in range(1,101):
            for iy in range(1,101):
                mean += noisyImage(ix, iy)

        mean = mean/10000.0

        for ix in range(1,101):
            for iy in range(1,101):
                var += (noisyImage(ix, iy) - mean)*(noisyImage(ix, iy) - mean)

        var = var/9999.0

        varElectrons = background*gain + readnoise
        varADU = varElectrons/(gain*gain)

        msg = 'background %e mean %e ' % (background, mean)
        self.assertTrue(numpy.abs(background/mean - 1.0) < 0.05, msg=msg)

        msg = 'var %e varADU %e ; ratio %e ; background %e' % (var, varADU, var/varADU, background)
        self.assertTrue(numpy.abs(var/varADU - 1.0) < 0.05, msg=msg)
Exemplo n.º 31
0
    def setUp(self):

        starName = os.path.join(lsst.utils.getPackageDir('sims_photUtils'),
                                'tests/cartoonSedTestData/starSed/')
        starName = os.path.join(starName, 'kurucz',
                                'km20_5750.fits_g40_5790.gz')
        self.starSED = Sed()
        self.starSED.readSED_flambda(starName)
        imsimband = Bandpass()
        imsimband.imsimBandpass()
        fNorm = self.starSED.calcFluxNorm(22.0, imsimband)
        self.starSED.multiplyFluxNorm(fNorm)

        hardwareDir = os.path.join(lsst.utils.getPackageDir('throughputs'),
                                   'baseline')
        componentList = [
            'detector.dat', 'm1.dat', 'm2.dat', 'm3.dat', 'lens1.dat',
            'lens2.dat', 'lens3.dat'
        ]
        self.skySed = Sed()
        self.skySed.readSED_flambda(os.path.join(hardwareDir, 'darksky.dat'))

        totalNameList = [
            'total_u.dat', 'total_g.dat', 'total_r.dat', 'total_i.dat',
            'total_z.dat', 'total_y.dat'
        ]

        self.bpList = []
        self.hardwareList = []
        for name in totalNameList:
            dummy = Bandpass()
            dummy.readThroughput(os.path.join(hardwareDir, name))
            self.bpList.append(dummy)

            dummy = Bandpass()
            hardwareNameList = [os.path.join(hardwareDir, name)]
            for component in componentList:
                hardwareNameList.append(os.path.join(hardwareDir, component))
            dummy.readThroughputList(hardwareNameList)
            self.hardwareList.append(dummy)

        self.filterNameList = ['u', 'g', 'r', 'i', 'z', 'y']
Exemplo n.º 32
0
    def getListOfBandpasses(self, nBp):
        """
        Generate a list of nBp bandpass names and bandpasses

        Intentionally do so a nonsense order so that we can test
        that order is preserved in the BandpassDict
        """
        dexList = numpy.random.random_integers(0, len(self.bandpassPossibilities)-1, nBp)
        bandpassNameList = []
        bandpassList = []
        for dex in dexList:
            name = self.bandpassPossibilities[dex]
            bp = Bandpass()
            bp.readThroughput(os.path.join(self.bandpassDir,'total_%s.dat' % name))
            while name in bandpassNameList:
                name += '0'
            bandpassNameList.append(name)
            bandpassList.append(bp)

        return bandpassNameList, bandpassList
    def getListOfBandpasses(self, nBp):
        """
        Generate a list of nBp bandpass names and bandpasses

        Intentionally do so a nonsense order so that we can test
        that order is preserved in the BandpassDict
        """
        dexList = numpy.random.random_integers(0, len(self.bandpassPossibilities)-1, nBp)
        bandpassNameList = []
        bandpassList = []
        for dex in dexList:
            name = self.bandpassPossibilities[dex]
            bp = Bandpass()
            bp.readThroughput(os.path.join(self.bandpassDir,'total_%s.dat' % name))
            while name in bandpassNameList:
                name += '0'
            bandpassNameList.append(name)
            bandpassList.append(bp)

        return bandpassNameList, bandpassList
Exemplo n.º 34
0
def buildLens(lensDir, addLosses=True):
    """
    Build the lens throughput curve from the files in lensDir.
    Returns a bandpass object.
    The coatings for the lens are in *_Coatings, the loss files are in *_Losses.
    The borosilicate glass throughput is in l*_Glass.dat; this file is smoothed using the
     savitzsky_golay function.
    The glass response is multiplied by the coatings and (if addLosses is True),
      also the loss curves.
    """
    lens = Bandpass()
    # Read the glass base file.
    glassfile = glob(os.path.join(lensDir, 'l*_Glass.dat'))
    if len(glassfile) != 1:
        raise ValueError('Expected a single glass file in this directory, found: ', glassfile)
    glassfile = glassfile[0]
    glass = Bandpass()
    glass.readThroughput(glassfile)
    # Smooth the glass response.
    smoothSb = savitzky_golay(glass.sb, 31, 3)
    lens = Bandpass()
    lens.setBandpass(glass.wavelen, smoothSb)
    # Read the broad band antireflective (BBAR) coatings files.
    bbars = _readCoatings(lensDir)
    # Multiply the bbars by the glass.
    wavelen, sb = lens.multiplyThroughputs(bbars.wavelen, bbars.sb)
    lens.setBandpass(wavelen, sb)
    # Add losses.
    if addLosses:
        loss = _readLosses(lensDir)
        wavelen, sb = lens.multiplyThroughputs(loss.wavelen, loss.sb)
        lens.setBandpass(wavelen, sb)
    # Verify that no values go significantly below zero.
    belowzero = np.where(lens.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if lens.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in lens throughput significantly below zero.')
    # If they are just small errors in interpolation, set to zero.
    lens.sb[belowzero] = 0
    return lens
def buildLens(lensDir, addLosses=True):
    """
    Build the lens throughput curve from the files in lensDir.
    Returns a bandpass object.
    The coatings for the lens are in *_Coatings, the loss files are in *_Losses.
    The borosilicate glass throughput is in l*_Glass.dat; this file is smoothed using the
     savitzsky_golay function.
    The glass response is multiplied by the coatings and (if addLosses is True),
      also the loss curves.
    """
    lens = Bandpass()
    # Read the glass base file.
    glassfile = glob(os.path.join(lensDir, 'l*_Glass.dat'))
    if len(glassfile) != 1:
        raise ValueError('Expected a single glass file in this directory, found: ', glassfile)
    glassfile = glassfile[0]
    glass = Bandpass()
    glass.readThroughput(glassfile)
    # Smooth the glass response.
    smoothSb = savitzky_golay(glass.sb, 31, 3)
    lens = Bandpass()
    lens.setBandpass(glass.wavelen, smoothSb)
    # Read the broad band antireflective (BBAR) coatings files.
    bbars = _readCoatings(lensDir)
    # Multiply the bbars by the glass.
    wavelen, sb = lens.multiplyThroughputs(bbars.wavelen, bbars.sb)
    lens.setBandpass(wavelen, sb)
    # Add losses.
    if addLosses:
        loss = _readLosses(lensDir)
        wavelen, sb = lens.multiplyThroughputs(loss.wavelen, loss.sb)
        lens.setBandpass(wavelen, sb)
    # Verify that no values go significantly below zero.
    belowzero = np.where(lens.sb < 0)
    # If there are QE values significantly < 0, raise an exception.
    if lens.sb[belowzero] < belowZeroThreshhold:
        raise ValueError('Found values in lens throughput significantly below zero.')
    # If they are just small errors in interpolation, set to zero.
    lens.sb[belowzero] = 0
    return lens
    def testApplication(self):
        """
        Test that PhotometricParameters get properly propagated into
        Sed methods.  We will test this using Sed.calcADU, since the ADU
        scale linearly with the appropriate parameter.
        """

        testSed = Sed()
        testSed.setFlatSED()

        testBandpass = Bandpass()
        testBandpass.readThroughput(os.path.join(lsst.utils.getPackageDir('throughputs'),
                                                 'baseline', 'total_g.dat'))

        control = testSed.calcADU(testBandpass,
                                  photParams=PhotometricParameters())

        testCase = PhotometricParameters(exptime=30.0)

        test = testSed.calcADU(testBandpass, photParams=testCase)

        self.assertGreater(control, 0.0)
        self.assertEqual(control, 0.5*test)
Exemplo n.º 37
0
    def loadTotalBandpassesFromFiles(
            cls,
            bandpassNames=['u', 'g', 'r', 'i', 'z', 'y'],
            bandpassDir=os.path.join(getPackageDir('throughputs'), 'baseline'),
            bandpassRoot='total_'):
        """
        This will take the list of band passes named by bandpassNames and load them into
        a BandpassDict

        The bandpasses loaded this way are total bandpasses: they account for instrumental
        and atmospheric transmission.

        @param [in] bandpassNames is a list of names identifying each filter.
        Defaults to ['u', 'g', 'r', 'i', 'z', 'y']

        @param [in] bandpassDir is the name of the directory where the bandpass files are stored

        @param [in] bandpassRoot contains the first part of the bandpass file name, i.e., it is assumed
        that the bandpasses are stored in files of the type

        bandpassDir/bandpassRoot_bandpassNames[i].dat

        if we want to load bandpasses for a telescope other than LSST, we would do so
        by altering bandpassDir and bandpassRoot

        @param [out] bandpassDict is a BandpassDict containing the loaded throughputs
        """

        bandpassList = []

        for w in bandpassNames:
            bandpassDummy = Bandpass()
            bandpassDummy.readThroughput(
                os.path.join(bandpassDir, "%s.dat" % (bandpassRoot + w)))
            bandpassList.append(bandpassDummy)

        return cls(bandpassList, bandpassNames)
Exemplo n.º 38
0
def getWiseThroughput(f):
    if f not in ["W1", "W2"]:
        raise ValueError("WISE does not have a {} filter".format(f))
    # the WISE throughputs are in a subdirectory WISE, not baseline
    throughputsDir = os.getenv('LSST_THROUGHPUTS_BASELINE')
    throughputsFile = os.path.join(throughputsDir, '..', 'WISE',
                                   'WISE_{}.dat'.format(f.lower()))

    # TODO hacky to set the min/max wavelengths, but I think readThroughput
    # complains because the files don't overlap in wavelength with what it's
    # expecting. Sad!
    wiseBand = Bandpass()
    if f == 'W1':
        wavelen_min = 2600
        wavelen_max = 4000
    elif f == 'W2':
        wavelen_min = 3890
        wavelen_max = 5560

    wiseBand.readThroughput(throughputsFile,
                            wavelen_min=wavelen_min,
                            wavelen_max=wavelen_max,
                            wavelen_step=10)
    return wiseBand
    def testApplication(self):
        """
        Test that PhotometricParameters get properly propagated into
        Sed methods.  We will test this using Sed.calcADU, since the ADU
        scale linearly with the appropriate parameter.
        """

        testSed = Sed()
        testSed.setFlatSED()

        testBandpass = Bandpass()
        testBandpass.readThroughput(
            os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline',
                         'total_g.dat'))

        control = testSed.calcADU(testBandpass,
                                  photParams=PhotometricParameters())

        testCase = PhotometricParameters(exptime=30.0)

        test = testSed.calcADU(testBandpass, photParams=testCase)

        self.assertTrue(control > 0.0)
        self.assertEqual(control, 0.5 * test)
Exemplo n.º 40
0
    def setUp(self):

        starName = os.path.join(lsst.utils.getPackageDir('sims_photUtils'),
                                'tests/cartoonSedTestData/starSed/')
        starName = os.path.join(starName, 'kurucz', 'km20_5750.fits_g40_5790.gz')
        self.starSED = Sed()
        self.starSED.readSED_flambda(starName)
        imsimband = Bandpass()
        imsimband.imsimBandpass()
        fNorm = self.starSED.calcFluxNorm(22.0, imsimband)
        self.starSED.multiplyFluxNorm(fNorm)

        hardwareDir = os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline')
        componentList = ['detector.dat', 'm1.dat', 'm2.dat', 'm3.dat',
                         'lens1.dat', 'lens2.dat', 'lens3.dat']
        self.skySed = Sed()
        self.skySed.readSED_flambda(os.path.join(hardwareDir, 'darksky.dat'))

        totalNameList = ['total_u.dat', 'total_g.dat', 'total_r.dat', 'total_i.dat',
                         'total_z.dat', 'total_y.dat']

        self.bpList = []
        self.hardwareList = []
        for name in totalNameList:
            dummy = Bandpass()
            dummy.readThroughput(os.path.join(hardwareDir, name))
            self.bpList.append(dummy)

            dummy = Bandpass()
            hardwareNameList = [os.path.join(hardwareDir, name)]
            for component in componentList:
                hardwareNameList.append(os.path.join(hardwareDir, component))
            dummy.readThroughputList(hardwareNameList)
            self.hardwareList.append(dummy)

        self.filterNameList = ['u', 'g', 'r', 'i', 'z', 'y']
Exemplo n.º 41
0
    def Load_Atmosphere(self, airmass=1.2):

        self.airmass = airmass
        if self.airmass > 0.:
            atmosphere = Bandpass()

            #official atmospheric simulation
            if not self.libradtran:
                path_atmos = os.path.join(self.atmosDir,
                                          'atmos_%d.dat' % (self.airmass * 10))
                if os.path.exists(path_atmos):
                    atmosphere.readThroughput(
                        os.path.join(self.atmosDir,
                                     'atmos_%d.dat' % (self.airmass * 10)))
                else:
                    atmosphere.readThroughput(
                        os.path.join(self.atmosDir, 'atmos.dat'))
                self.atmos = Bandpass(wavelen=atmosphere.wavelen,
                                      sb=atmosphere.sb)
            else:  # with libradtran
                path, thefile = ProcessSimulationaer(airmass, atm_pwv,
                                                     atm_ozone, atm_wl0,
                                                     atm_aer)
                #path,thefile=ProcessSimulation(am,pwv,ozone)
                atmdata = np.loadtxt(os.path.join(path, thefile))
                wl = atmdata[:, 0]
                atm = atmdata[:, 1]
                func = interp1d(wl, atm, kind='linear')
                transm = func(WL)
                atmosphere.wavelen = WL
                atmosphere.sb = transm
                self.atmos = Bandpass(wavelen=WL, sb=transm)

            for f in self.filterlist:
                wavelen, sb = self.lsst_system[f].multiplyThroughputs(
                    atmosphere.wavelen, atmosphere.sb)
                self.lsst_atmos[f] = Bandpass(wavelen=wavelen, sb=sb)

            if self.aerosol:
                atmosphere_aero = Bandpass()
                atmosphere_aero.readThroughput(
                    os.path.join(self.atmosDir,
                                 'atmos_%d_aerosol.dat' % (self.airmass * 10)))
                self.atmos_aerosol = Bandpass(wavelen=atmosphere_aero.wavelen,
                                              sb=atmosphere_aero.sb)

                for f in self.filterlist:
                    wavelen, sb = self.lsst_system[f].multiplyThroughputs(
                        atmosphere_aero.wavelen, atmosphere_aero.sb)
                    self.lsst_atmos_aerosol[f] = Bandpass(wavelen=wavelen,
                                                          sb=sb)
        else:
            for f in self.filterlist:
                self.lsst_atmos[f] = self.lsst_system[f]
                self.lsst_atmos_aerosol[f] = self.lsst_system[f]
Exemplo n.º 42
0
    def Load_Atmosphere(self, airmass=1.2):
        """ Load atmosphere files
        and convolve with transmissions

        Parameters
        --------------
        airmass : float,opt
          airmass value
          Default : 1.2
        """
        self.airmass = airmass
        if self.airmass > 0.:
            atmosphere = Bandpass()
            path_atmos = os.path.join(self.atmosDir,
                                      'atmos_%d.dat' % (self.airmass * 10))
            if os.path.exists(path_atmos):
                atmosphere.readThroughput(
                    os.path.join(self.atmosDir,
                                 'atmos_%d.dat' % (self.airmass * 10)))
            else:
                atmosphere.readThroughput(
                    os.path.join(self.atmosDir, 'atmos.dat'))
            self.atmos = Bandpass(wavelen=atmosphere.wavelen, sb=atmosphere.sb)

            for f in self.filterlist:
                wavelen, sb = self.lsst_system[f].multiplyThroughputs(
                    atmosphere.wavelen, atmosphere.sb)
                self.lsst_atmos[f] = Bandpass(wavelen=wavelen, sb=sb)

            if self.aerosol_b:
                atmosphere_aero = Bandpass()
                atmosphere_aero.readThroughput(
                    os.path.join(self.atmosDir,
                                 'atmos_%d_aerosol.dat' % (self.airmass * 10)))
                self.atmos_aerosol = Bandpass(wavelen=atmosphere_aero.wavelen,
                                              sb=atmosphere_aero.sb)

                for f in self.filterlist:
                    wavelen, sb = self.lsst_system[f].multiplyThroughputs(
                        atmosphere_aero.wavelen, atmosphere_aero.sb)
                    self.lsst_atmos_aerosol[f] = Bandpass(wavelen=wavelen,
                                                          sb=sb)
        else:
            for f in self.filterlist:
                self.lsst_atmos[f] = self.lsst_system[f]
                self.lsst_atmos_aerosol[f] = self.lsst_system[f]
Exemplo n.º 43
0
class MoObs(MoOrbits):
    """
    Class to generate observations of a set of moving objects.
    Inherits from moOrbits (in order to read and save orbits).
    """

    def setTimes(self, timestep=1., ndays=1., timestart=49353.):
        """
        Generate and return an array for oorb of the ephemeris times desired.
        @ timestep : timestep for ephemeris generation (days)
        @ ndays    : number of days to generate ephemerides for (days)
        @ timestart : starting time of ephemerides (MJD)
        """
        # Extend times beyond first/last observation, so that interpolation doesn't fail
        timestart = timestart - timestep
        timeend = timestart + ndays + timestep
        times = np.arange(timestart, timeend + timestep/2.0, timestep)
        # For pyoorb, we need to tag times with timescales;
        # 1= MJD_UTC, 2=UT1, 3=TT, 4=TAI
        self.ephTimes = np.array(zip(times, repeat(4, len(times))), dtype='double', order='F')

    def _packOorbElem(self, sso=None):
        """
        Convert row from pandas dataframe (or numpy recarray) of orbital elements into the array OpenOrb needs as input.
        'sso' can be the orbital elements of a single object or of multiple objects.
        To normalize the column names to those expected here, read in data using 'readOrbits'.
        """
        # Python oorb element format:
        #
        # 0: orbitId  (cannot be a string)
        # 1 - 6: orbital elements, using radians for angles
        # 7: element type code
        #       2 = cometary - means timescale is TT, too
        #       3 = keplerians - timescale?
        # 8: epoch
        # 9: timescale for the epoch; 1= MJD_UTC, 2=UT1, 3=TT, 4=TAI
        # 10: magHv
        # 11: G
        #
        #  so we have to do a little translating from the orbits DataFrame to the elements we want in this array.
        if sso is None:
            sso = self.orbits
        # Do we have a single item (Series) or multiples (Dataframe)?
        if isinstance(sso, pd.Series):
            # Passed a single SSO in Series.
            nSso = 1
        elif isinstance(sso, pd.DataFrame):
            # Multiple SSO in dataframe.
            nSso = len(sso)
        else:
            if len(sso.shape) == 0:
                # Single SSO, in a numpy array.
                nSso = 1
            else:
                # Multiple SSSO in numpy array (or something else?).
                nSso = len(sso)
        if nSso == 1:
            orbids = 0
            elem_type = 2
            epoch_type = 3
        else:
            orbids = np.arange(0, nSso, 1)
            elem_type = np.zeros(nSso) + 2
            epoch_type = np.zeros(nSso) + 3
        # Convert to format for pyoorb, INCLUDING converting inclination, node, argperi to RADIANS
        oorbElem = np.column_stack((orbids, sso['q'], sso['e'], np.radians(sso['inc']),
                                     np.radians(sso['node']), np.radians(sso['argPeri']),
                                     sso['tPeri'], elem_type, sso['epoch'], epoch_type,
                                     sso['H'], sso['g']))
        return oorbElem

    def setupOorb(self):
        """
        Initialize oorb. (call once)
        """
        oo.pyoorb.oorb_init(ephemeris_fname="")

    def _generateOorbEphs(self, oorbArray, ephTimes=None, obscode=807):
        """
        Generate ephemerides.
        """
        if ephTimes is None:
            ephTimes = self.ephTimes
        oorbephems, err = oo.pyoorb.oorb_ephemeris(in_orbits = oorbArray, in_obscode=obscode, in_date_ephems=ephTimes)
        if err != 0:
            print 'Oorb returned error %s' %(err)
        return oorbephems

    def _unpackOorbEphs(self, oorbephems, byObject=True):
        """
        Given oorb ephemeris array (shape = object / times / eph@time),
        Return a numpy array aranged with
         columns = ['delta', 'ra', 'dec', 'mag', 'time', 'timescale', 'dradt', 'ddecdt', 'phase', 'solarelon']
         as the second
        grouped either by object (i.e. length of ra array == length of times) (default)
        or grouped by time (i.e. length of ra array == number of objects) (if byObject not true).
        """
        # Python oorb ephem array format:
        #   [objid][time][ephemeris information @ that time]
        # 0 = distance (geocentric distance)
        # 1 = ra (deg)
        # 2 = dec (deg)
        # 3 = mag
        # 4 = ephem mjd
        # 5 = ephem mjd timescale
        # 6 = dra/dt (deg/day) sky motion
        # 7 = ddec/dt (deg/day) sky motion
        # 8 = phase angle (deg)
        # 9 = solar elongation angle (deg)
        # So usually we want to swap the axes at least, so that instead of all the ephemeris information @ a particular time
        # being the accessible bit of information, we have all the RA values over time for a single object ('byObject')
        # Alternatively, we may want all the RA values for all objects at one time.
        #     This is also an option, by setting 'byObject' to False.
        ephs = np.swapaxes(oorbephems, 2, 0)
        # oorbcols=['delta', 'ra', 'dec', 'magV', 'time', 'timescale', 'dradt', 'ddecdt', 'phase', 'solarelon']
        velocity = np.sqrt(ephs[6]**2 + ephs[7]**2)
        if byObject:
            ephs = np.swapaxes(ephs, 2, 1)
            velocity = np.swapaxes(velocity, 1, 0)
        # Create a numpy recarray. We're deviating from the DataFrame here probably mostly due to history.
        ephs = np.rec.fromarrays([ephs[0], ephs[1], ephs[2], ephs[3], ephs[4],
                                  ephs[6], ephs[7], ephs[8], ephs[9], velocity],
                                  names=['delta', 'ra', 'dec', 'magV', 'time', 'dradt',
                                         'ddecdt', 'phase', 'solarelon','velocity'])
        return ephs

    def generateEphs(self, sso=None, ephTimes=None):
        """
        Combines several private methods to pack and unpack oorb-format orbital elements and ephemerides,
        into a single easy-access point to generate numpy arrays of ephemerides.

        Use the individual private methods if you want to unpack the ephemerides in a manner other than 'byObject'.
        """
        if sso is None:
            sso = self.orbits
        oorbelems = self._packOorbElem(sso=sso)
        oorbephs = self._generateOorbEphs(oorbelems, ephTimes=ephTimes)
        ephs = self._unpackOorbEphs(oorbephs, byObject=True)
        return ephs

    # Linear interpolation
    def interpolateEphs(self, ephs, i=0):
        """
        Generate linear interpolations between the quantities in ephs over time.
        """
        interpfuncs = {}
        for n in ephs.dtype.names:
            if n == 'time':
                continue
            interpfuncs[n] = interpolate.interp1d(ephs['time'][i], ephs[n][i], kind='linear',
                                                  assume_sorted=True, copy=False)
        return interpfuncs

    def _setupCamera(self):
        """
        Initialize camera mapper, etc.
        """
        self.mapper = LsstSimMapper()
        self.camera = self.mapper.camera
        self.epoch = 2000.0
        self.cameraFov=np.radians(2.1)

    def ssoInFov(self, interpfuncs, simdata, rFov=np.radians(1.75),
                 useCamera=True,
                 simdataRaCol = 'fieldRA', simdataDecCol='fieldDec'):
        """
        Return the indexes of the simdata observations where the object was inside the fov.
        """
        # See if the object is within 'rFov' of the center of the boresight.
        raSso = np.radians(interpfuncs['ra'](simdata['expMJD']))
        decSso = np.radians(interpfuncs['dec'](simdata['expMJD']))
        sep = haversine(raSso, decSso, simdata[simdataRaCol], simdata[simdataDecCol])
        if not useCamera:
            idxObsRough = np.where(sep<rFov)[0]
            return idxObsRough
        # Or go on and use the camera footprint.
        try:
            self.camera
        except AttributeError:
            self._setupCamera()
        idxObs = []
        idxObsRough = np.where(sep<self.cameraFov)[0]
        for idx in idxObsRough:
            mjd = simdata[idx]['expMJD']
            obs_metadata = ObservationMetaData(unrefractedRA=np.degrees(simdata[idx][simdataRaCol]),
                                               unrefractedDec=np.degrees(simdata[idx][simdataDecCol]),
                                               rotSkyPos=np.degrees(simdata[idx]['rotSkyPos']),
                                               mjd=simdata[idx]['expMJD'])
            raObj = np.radians(np.array([interpfuncs['ra'](simdata[idx]['expMJD'])]))
            decObj = np.radians(np.array([interpfuncs['dec'](simdata[idx]['expMJD'])]))
            raObj, decObj = observedFromICRS(raObj, decObj, obs_metadata=obs_metadata, epoch=self.epoch)
            chipNames = findChipName(ra=raObj,dec=decObj, epoch=self.epoch, camera=self.camera, obs_metadata=obs_metadata)
            if chipNames != [None]:
                idxObs.append(idx)
        idxObs = np.array(idxObs)
        return idxObs


    def _calcColors(self, sedname='C.dat'):
        """
        Calculate the colors for a moving object with sed 'sedname'.
        """
        # Do we need to read in the LSST bandpasses?
        try:
            self.lsst
        except AttributeError:
            filterdir = os.getenv('LSST_THROUGHPUTS_BASELINE')
            filterlist = ('u', 'g', 'r', 'i', 'z', 'y')
            self.lsst ={}
            for f in filterlist:
                self.lsst[f] = Bandpass()
                self.lsst[f].readThroughput(os.path.join(filterdir, 'total_'+f+'.dat'))
            self.vband = Bandpass()
            self.vband.readThroughput('harris_V.dat')
            self.colors = {}
        # See if the sed's colors are in memory already.
        if sedname not in self.colors:
            moSed = Sed()
            moSed.readSED_flambda(sedname)
            vmag = moSed.calcMag(self.vband)
            self.colors[sedname] = {}
            for f in filterlist:
                self.colors[sedname][f] = moSed.calcMag(self.lsst[f]) - vmag
        return self.colors[sedname]


    def _calcMagLosses(self, velocity, seeing, texp=30.):
        """
        Calculate the magnitude losses due to trailing and not matching the point-source detection filter.
        """
        a_trail = 0.76
        b_trail = 1.16
        a_det = 0.42
        b_det = 0.00
        x = velocity * texp / seeing / 24.0
        dmagTrail = 1.25 * np.log10(1 + a_trail*x**2/(1+b_trail*x))
        dmagDetect = 1.25 * np.log10(1 + a_det*x**2 / (1+b_det*x))
        return dmagTrail, dmagDetect

    def _openOutput(self, outfileName):
        self.outfile = open(outfileName, 'w')
        self.wroteHeader = False

    def writeObs(self, objId, interpfuncs, simdata, idxObs, outfileName='out.txt',
                 sedname='C.dat', tol=1e-8,
                 seeingCol='finSeeing', expTimeCol='visitExpTime'):
        """
        Call for each object; write out the observations of each object.
        """
        # Return if there's nothing to write out.
        if len(idxObs) == 0:
            return
        # Open file if needed.
        try:
            self.outfile
        except AttributeError:
            self._openOutput(outfileName)
        # Calculate the ephemerides for the object, using the interpfuncs, for the times in simdata[idxObs].
        tvis = simdata['expMJD'][idxObs]
        ephs = np.recarray([len(tvis)], dtype=([('delta', '<f8'), ('ra', '<f8'), ('dec', '<f8'),
                                                ('magV', '<f8'), ('time', '<f8'), ('dradt', '<f8'), ('ddecdt', '<f8'),
                                                ('phase', '<f8'), ('solarelon', '<f8'), ('velocity', '<f8')]))
        for n in interpfuncs:
            ephs[n] = interpfuncs[n](tvis)
        ephs['time'] = tvis
        # Calculate the extra columns we want to write out (dmag due to color, trailing loss, and detection loss)
        # First calculate and match the color dmag term.
        dmagColor = np.zeros(len(idxObs), float)
        dmagColorDict = self._calcColors(sedname)
        filterlist = np.unique(simdata[idxObs]['filter'])
        for f in filterlist:
            if f not in dmagColorDict:
                raise UserWarning('Could not find filter %s in calculated colors!' %(f))
            match = np.where(simdata[idxObs]['filter'] == f)[0]
            dmagColor[match] = dmagColorDict[f]
        magFilter = ephs['magV'] + dmagColor
        # Calculate trailing and detection loses.
        dmagTrail, dmagDetect = self._calcMagLosses(ephs['velocity'], simdata[seeingCol][idxObs],
                                                    simdata[expTimeCol][idxObs])
        # Turn into a recarray so it's easier below.
        dmags = np.rec.fromarrays([magFilter, dmagColor, dmagTrail, dmagDetect],
                                  names=['magFilter', 'dmagColor', 'dmagTrail', 'dmagDetect'])

        outCols = ['objId',] + list(ephs.dtype.names) + list(simdata.dtype.names) + list(dmags.dtype.names)

        if not self.wroteHeader:
            writestring = ''
            for col in outCols:
                writestring += '%s ' %(col)
            self.outfile.write('%s\n' %(writestring))
            self.wroteHeader = True

        # Write results.
        for eph, simdat, dm in zip(ephs, simdata[idxObs], dmags):
            writestring = '%s ' %(objId)
            for col in ephs.dtype.names:
                writestring += '%s ' %(eph[col])
            for col in simdat.dtype.names:
                writestring += '%s ' %(simdat[col])
            for col in dm.dtype.names:
                writestring += '%s ' %(dm[col])
            self.outfile.write('%s\n' %(writestring))
        self.outfile.flush()
# This is an example case of using the Sed.py and Bandpass.py classes. 
# Only some of the (probably most often used) functionality is illustrated here,
#  so please see the comments in Sed and Bandpass for more information.

import lsst.sims.photUtils.Sed as Sed
import lsst.sims.photUtils.Bandpass as Bandpass

# Note that Bandpass and Sed are set up for NANOMETERS units on input data

# Instantiate a Bandpass object to hold the throughput information
rband = Bandpass()
# Read the bandpass data file into that object -
#  (note exampleBandpass.dat contains THROUGHPUT information, not PHI)
bpfile = 'exampleBandpass.dat'
rband.readThroughput(bpfile)

# Instantiate a Sed object to hold the spectral energy distribution information
star = Sed()
# Read the Sed data file into that object -
#  (note that exampleSED.dat contains wavelength/F_lambda .. but is possible to also
#    read in wavelength/F_nu data using readSED_fnu)
sedfile = 'exampleSED.dat'
star.readSED_flambda(sedfile)

print ""
print "Read %s into Bandpass and %s into Sed." %(bpfile, sedfile)

# Simply calculate the magnitude of this source in the bandpass.
mag = star.calcMag(rband)
    def testAlternateNormalizingBandpass(self):
        """
        A reiteration of testAddingToList, but testing with a non-imsimBandpass
        normalizing bandpass
        """
        normalizingBand = Bandpass()
        normalizingBand.readThroughput(os.path.join(getPackageDir('throughputs'),'baseline','total_r.dat'))
        nSed = 10
        sedNameList_0 = self.getListOfSedNames(nSed)
        magNormList_0 = numpy.random.random_sample(nSed)*5.0 + 15.0
        internalAvList_0 = numpy.random.random_sample(nSed)*0.3 + 0.1
        redshiftList_0 = numpy.random.random_sample(nSed)*5.0
        galacticAvList_0 = numpy.random.random_sample(nSed)*0.3 + 0.1
        wavelen_match = numpy.arange(300.0, 1500.0, 10.0)
        testList = SedList(sedNameList_0, magNormList_0,
                           normalizingBandpass=normalizingBand,
                           internalAvList=internalAvList_0,
                           redshiftList=redshiftList_0, galacticAvList=galacticAvList_0,
                           wavelenMatch=wavelen_match)


        sedNameList_1 = self.getListOfSedNames(nSed)
        magNormList_1 = numpy.random.random_sample(nSed)*5.0 + 15.0

        internalAvList_1 = numpy.random.random_sample(nSed)*0.3 + 0.1

        redshiftList_1 = numpy.random.random_sample(nSed)*5.0

        galacticAvList_1 = numpy.random.random_sample(nSed)*0.3 + 0.1


        testList.loadSedsFromList(sedNameList_1, magNormList_1,
                                  internalAvList=internalAvList_1,
                                  galacticAvList=galacticAvList_1,
                                  redshiftList=redshiftList_1)

        self.assertEqual(len(testList), 2*nSed)
        numpy.testing.assert_array_equal(wavelen_match, testList.wavelenMatch)

        for ix in range(len(sedNameList_0)):
            self.assertAlmostEqual(internalAvList_0[ix], testList.internalAvList[ix], 10)
            self.assertAlmostEqual(galacticAvList_0[ix], testList.galacticAvList[ix], 10)
            self.assertAlmostEqual(redshiftList_0[ix], testList.redshiftList[ix], 10)


        for ix in range(len(sedNameList_1)):
            self.assertAlmostEqual(internalAvList_1[ix], testList.internalAvList[ix+nSed], 10)
            self.assertAlmostEqual(galacticAvList_1[ix], testList.galacticAvList[ix+nSed], 10)
            self.assertAlmostEqual(redshiftList_1[ix], testList.redshiftList[ix+nSed], 10)

        for ix, (name, norm, iav, gav, zz) in \
          enumerate(zip(sedNameList_0, magNormList_0, internalAvList_0, \
                     galacticAvList_0, redshiftList_0)):

            sedControl = Sed()
            sedControl.readSED_flambda(os.path.join(self.sedDir, name+'.gz'))

            fnorm = sedControl.calcFluxNorm(norm, normalizingBand)
            sedControl.multiplyFluxNorm(fnorm)

            a_coeff, b_coeff = sedControl.setupCCMab()
            sedControl.addCCMDust(a_coeff, b_coeff, A_v=iav)

            sedControl.redshiftSED(zz, dimming=True)
            sedControl.resampleSED(wavelen_match=wavelen_match)

            a_coeff, b_coeff = sedControl.setupCCMab()
            sedControl.addCCMDust(a_coeff, b_coeff, A_v=gav)

            sedTest = testList[ix]

            numpy.testing.assert_array_equal(sedControl.wavelen, sedTest.wavelen)
            numpy.testing.assert_array_equal(sedControl.flambda, sedTest.flambda)
            numpy.testing.assert_array_equal(sedControl.fnu, sedTest.fnu)

        for ix, (name, norm, iav, gav, zz) in \
            enumerate(zip(sedNameList_1, magNormList_1, internalAvList_1, \
                          galacticAvList_1, redshiftList_1)):

            sedControl = Sed()
            sedControl.readSED_flambda(os.path.join(self.sedDir, name+'.gz'))

            fnorm = sedControl.calcFluxNorm(norm, normalizingBand)
            sedControl.multiplyFluxNorm(fnorm)

            a_coeff, b_coeff = sedControl.setupCCMab()
            sedControl.addCCMDust(a_coeff, b_coeff, A_v=iav)

            sedControl.redshiftSED(zz, dimming=True)

            sedControl.resampleSED(wavelen_match=wavelen_match)

            a_coeff, b_coeff = sedControl.setupCCMab()
            sedControl.addCCMDust(a_coeff, b_coeff, A_v=gav)

            sedTest = testList[ix+nSed]

            numpy.testing.assert_array_equal(sedControl.wavelen, sedTest.wavelen)
            numpy.testing.assert_array_equal(sedControl.flambda, sedTest.flambda)
            numpy.testing.assert_array_equal(sedControl.fnu, sedTest.fnu)
Exemplo n.º 46
0
                           'physical characteristics for '
                           'sub_dir %s' % sub_dir)



if __name__ == "__main__":

    # Load the SDSS bandpasses
    bp_dir = os.path.join(getPackageDir('throughputs'), 'sdss')
    bp_name_list = ['doi_u.dat', 'doi_g.dat', 'doi_r.dat', 'doi_i.dat',
                    'doi_z.dat']

    bp_list = []
    for name in bp_name_list:
        bp = Bandpass()
        bp.readThroughput(os.path.join(bp_dir, name))
        bp_list.append(bp)

    # load the imsim bandpass
    imsimBand = Bandpass()
    imsimBand.imsimBandpass()

    #star_dir = os.path.join(getPackageDir('sims_sed_library'), 'starSED')
    sub_dir_list = ['kurucz', 'mlt', 'wDs']
    star_dir = os.path.join(getPackageDir('sims_sed_library'), 'starSED')
    
    t_start = time.time()

    # loop through the kurucz, mlt, and wDs sub-directories of
    # sims_sed_library/starSED, calculating the required magnitudes
    # for each of the SED files found.
    # Build the separate vendor detectors.
    qevendors = {}
    # Vendor 1
    qevendors[1] = bu.buildVendorDetector(os.path.join(defaultDirs['detector'], 'vendor1'), addLosses)
    # Vendor 2
    qevendors[2] = bu.buildVendorDetector(os.path.join(defaultDirs['detector'], 'vendor2'), addLosses)
    # Generic 'minimum' detector throughputs.
    qevendors['Min'] = bu.buildDetector(defaultDirs['detector'], addLosses)
    throughputs['detector'] = qevendors['Min']
    bu.plotBandpasses(qevendors, title='Combining Vendor Detector Responses')

    # Read the previously generated 'intermediate' file and plot the comparison.
    comparison = Bandpass()
    oldDetector = '../intermediateFiles/components/camera/detThroughput.dat'
    comparison.readThroughput(oldDetector)
    # Plot old and new detectors.
    plotDict = {'New Detector':throughputs['detector'], 'Old Detector':comparison}
    bu.plotBandpasses(plotDict, title='Compare Detector Throughputs')

    # Build and compare the lens throughput curves, for lens1/2/3.
    for lens in ('lens1', 'lens2', 'lens3'):
        throughputs[lens] = bu.buildLens(defaultDirs[lens], addLosses)
        # Read the old intermediate file version.
        comparison.readThroughput('../intermediateFiles/components/camera/%sThroughput.dat'
                                  %(lens))
        plotDict = {'New %s' %(lens): throughputs[lens], 'Old %s' %(lens): comparison}
        bu.plotBandpasses(plotDict, title='Compare %s' %(lens))

    # Build and compare the filter curves.
    filters = bu.buildFilters(defaultDirs['filters'], addLosses)
Exemplo n.º 48
0
    def testObjectPlacement(self):
        """
        Test that GalSim places objects on the correct pixel by drawing
        images, reading them in, and then comparing the flux contained in
        circles of 2 fwhm radii about the object's expected positions with
        the actual expected flux of the objects.
        """
        scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testObjectPlacement-')
        catName = os.path.join(scratchDir, 'placementCatalog.dat')
        imageRoot = os.path.join(scratchDir, 'placementImage')
        dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat')

        cameraDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData')
        camera = ReturnCamera(cameraDir)
        detector = camera[0]
        imageName = '%s_%s_u.fits' % (imageRoot, detector.getName())

        controlSed = Sed()
        controlSed.readSED_flambda(os.path.join(getPackageDir('sims_sed_library'),
                                                'flatSED', 'sed_flat.txt.gz'))

        uBandpass = Bandpass()
        uBandpass.readThroughput(os.path.join(getPackageDir('throughputs'),
                                              'baseline', 'total_u.dat'))

        controlBandpass = Bandpass()
        controlBandpass.imsimBandpass()

        ff = controlSed.calcFluxNorm(self.magNorm, uBandpass)
        controlSed.multiplyFluxNorm(ff)
        a_int, b_int = controlSed.setupCCMab()
        controlSed.addCCMDust(a_int, b_int, A_v=0.1, R_v=3.1)

        nSamples = 3
        rng = np.random.RandomState(42)
        pointingRaList = rng.random_sample(nSamples)*360.0
        pointingDecList = rng.random_sample(nSamples)*180.0 - 90.0
        rotSkyPosList = rng.random_sample(nSamples)*360.0
        fwhmList = rng.random_sample(nSamples)*1.0 + 0.3

        actualCounts = None

        for pointingRA, pointingDec, rotSkyPos, fwhm in \
        zip(pointingRaList, pointingDecList, rotSkyPosList, fwhmList):

            obs = ObservationMetaData(pointingRA=pointingRA,
                                      pointingDec=pointingDec,
                                      boundType='circle',
                                      boundLength=4.0,
                                      mjd=49250.0,
                                      rotSkyPos=rotSkyPos)

            xDisplacementList = rng.random_sample(nSamples)*60.0-30.0
            yDisplacementList = rng.random_sample(nSamples)*60.0-30.0
            create_text_catalog(obs, dbFileName, xDisplacementList, yDisplacementList,
                                mag_norm=[self.magNorm]*len(xDisplacementList))
            db = placementFileDBObj(dbFileName, runtable='test')
            cat = placementCatalog(db, obs_metadata=obs)
            cat.camera_wrapper = GalSimCameraWrapper(camera)
            if actualCounts is None:
                actualCounts = controlSed.calcADU(uBandpass, cat.photParams)

            psf = SNRdocumentPSF(fwhm=fwhm)
            cat.setPSF(psf)

            cat.write_catalog(catName)
            cat.write_images(nameRoot=imageRoot)

            objRaList = []
            objDecList = []
            with open(catName, 'r') as inFile:
                for line in inFile:
                    if line[0] != '#':
                        words = line.split(';')
                        objRaList.append(np.radians(np.float(words[2])))
                        objDecList.append(np.radians(np.float(words[3])))

            objRaList = np.array(objRaList)
            objDecList = np.array(objDecList)

            self.assertGreater(len(objRaList), 0)  # make sure we aren't testing
                                                   # an empty catalog/image

            self.check_placement(imageName, objRaList, objDecList,
                                 [fwhm]*len(objRaList),
                                 np.array([actualCounts]*len(objRaList)),
                                 cat.photParams.gain, detector, camera, obs, epoch=2000.0)

            if os.path.exists(dbFileName):
                os.unlink(dbFileName)
            if os.path.exists(catName):
                os.unlink(catName)
            if os.path.exists(imageName):
                os.unlink(imageName)

        if os.path.exists(scratchDir):
            shutil.rmtree(scratchDir)
class CartoonUncertaintyTestCase(unittest.TestCase):
    """
    This unit test suite will verify that our 'arbitrarily extensible' framework
    for writing magnitude uncertainty getters actually behaves as advertised
    """

    def setUp(self):
        self.normband = Bandpass()
        self.normband.imsimBandpass()
        self.uband = Bandpass()
        self.uband.readThroughput(os.path.join(getPackageDir('sims_photUtils'), 'tests',
                                  'cartoonSedTestData', 'test_bandpass_u.dat'))
        self.gband = Bandpass()
        self.gband.readThroughput(os.path.join(getPackageDir('sims_photUtils'), 'tests',
                                  'cartoonSedTestData', 'test_bandpass_g.dat'))

    def test_stars(self):
        obs = ObservationMetaData(bandpassName=['c_u', 'c_g'], m5=[25.0, 26.0])

        db_dtype = np.dtype([('id', np.int),
                             ('raJ2000', np.float),
                             ('decJ2000', np.float),
                             ('sedFilename', str, 100),
                             ('magNorm', np.float),
                             ('galacticAv', np.float)])

        inputDir = os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData')
        inputFile = os.path.join(inputDir, 'IndicesTestCatalogStars.txt')
        db = fileDBObject(inputFile, dtype=db_dtype, runtable='test', idColKey='id')
        cat = CartoonStars(db, obs_metadata=obs)
        with lsst.utils.tests.getTempFilePath('.txt') as catName:
            cat.write_catalog(catName)
            dtype = np.dtype([(name, np.float) for name in cat.column_outputs])
            controlData = np.genfromtxt(catName, dtype=dtype, delimiter=',')

        db_columns = db.query_columns(['id', 'raJ2000', 'decJ2000', 'sedFilename', 'magNorm', 'galacticAv'])

        sedDir = os.path.join(getPackageDir('sims_sed_library'), 'starSED', 'kurucz')

        for ix, line in enumerate(next(db_columns)):
            spectrum = Sed()
            spectrum.readSED_flambda(os.path.join(sedDir, line[3]))
            fnorm = spectrum.calcFluxNorm(line[4], self.normband)
            spectrum.multiplyFluxNorm(fnorm)
            a_x, b_x = spectrum.setupCCM_ab()
            spectrum.addDust(a_x, b_x, A_v=line[5])
            umag = spectrum.calcMag(self.uband)
            self.assertAlmostEqual(umag, controlData['cartoon_u'][ix], 3)
            gmag = spectrum.calcMag(self.gband)
            self.assertAlmostEqual(gmag, controlData['cartoon_g'][ix], 3)
            umagError, gamma = calcMagError_m5(umag, self.uband, obs.m5['c_u'], PhotometricParameters())
            gmagError, gamma = calcMagError_m5(gmag, self.gband, obs.m5['c_g'], PhotometricParameters())
            self.assertAlmostEqual(umagError, controlData['sigma_cartoon_u'][ix], 3)
            self.assertAlmostEqual(gmagError, controlData['sigma_cartoon_g'][ix], 3)

    def test_mixed_stars(self):
        """
        Here we will test the (somewhat absurd) case of a catalog with two different bandpasses
        (lsst_ and cartoon_) in order to verify that gamma values are being cached correctly
        """

        lsst_u_band = Bandpass()
        lsst_u_band.readThroughput(os.path.join(getPackageDir('throughputs'), 'baseline', 'total_u.dat'))
        lsst_g_band = Bandpass()
        lsst_g_band.readThroughput(os.path.join(getPackageDir('throughputs'), 'baseline', 'total_g.dat'))

        obs = ObservationMetaData(bandpassName=['c_u', 'c_g', 'u', 'g'],
                                  m5=[25.0, 26.0, 15.0, 16.0])
        # make the difference in m5 between the two bandpass systems extreme
        # so that, in the unit test, we can be sure that the correct values
        # are being used for the correct getters

        db_dtype = np.dtype([('id', np.int),
                             ('raJ2000', np.float),
                             ('decJ2000', np.float),
                             ('sedFilename', str, 100),
                             ('magNorm', np.float),
                             ('galacticAv', np.float)])

        inputDir = os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData')
        inputFile = os.path.join(inputDir, 'IndicesTestCatalogStars.txt')
        db = fileDBObject(inputFile, dtype=db_dtype, runtable='test', idColKey='id')
        cat = CartoonStars(db, obs_metadata=obs, column_outputs=['lsst_u', 'lsst_g',
                                                                 'sigma_lsst_u', 'sigma_lsst_g'])
        with lsst.utils.tests.getTempFilePath('.txt') as catName:
            cat.write_catalog(catName)
            dtype = np.dtype([(name, np.float) for name in cat._column_outputs])
            controlData = np.genfromtxt(catName, dtype=dtype, delimiter=',')

        db_columns = db.query_columns(['id', 'raJ2000', 'decJ2000', 'sedFilename', 'magNorm', 'galacticAv'])

        sedDir = os.path.join(getPackageDir('sims_sed_library'), 'starSED', 'kurucz')

        for ix, line in enumerate(next(db_columns)):
            spectrum = Sed()
            spectrum.readSED_flambda(os.path.join(sedDir, line[3]))
            fnorm = spectrum.calcFluxNorm(line[4], self.normband)
            spectrum.multiplyFluxNorm(fnorm)
            a_x, b_x = spectrum.setupCCM_ab()
            spectrum.addDust(a_x, b_x, A_v=line[5])
            umag = spectrum.calcMag(self.uband)
            self.assertAlmostEqual(umag, controlData['cartoon_u'][ix], 3)
            gmag = spectrum.calcMag(self.gband)
            self.assertAlmostEqual(gmag, controlData['cartoon_g'][ix], 3)
            lsst_umag = spectrum.calcMag(lsst_u_band)
            self.assertAlmostEqual(lsst_umag, controlData['lsst_u'][ix], 3)
            lsst_gmag = spectrum.calcMag(lsst_g_band)
            self.assertAlmostEqual(lsst_gmag, controlData['lsst_g'][ix], 3)
            umagError, gamma = calcMagError_m5(umag, self.uband, obs.m5['c_u'], PhotometricParameters())
            gmagError, gamma = calcMagError_m5(gmag, self.gband, obs.m5['c_g'], PhotometricParameters())
            self.assertAlmostEqual(umagError, controlData['sigma_cartoon_u'][ix], 3)
            self.assertAlmostEqual(gmagError, controlData['sigma_cartoon_g'][ix], 3)

            lsst_umagError, gamma = calcMagError_m5(lsst_umag, lsst_u_band,
                                                    obs.m5['u'], PhotometricParameters())
            lsst_gmagError, gamma = calcMagError_m5(lsst_gmag, lsst_g_band,
                                                    obs.m5['g'], PhotometricParameters())

            self.assertAlmostEqual(lsst_umagError, controlData['sigma_lsst_u'][ix], 3)
            self.assertAlmostEqual(lsst_gmagError, controlData['sigma_lsst_g'][ix], 3)
            self.assertGreater(np.abs(lsst_umagError-umagError), 0.01)
            self.assertGreater(np.abs(lsst_gmagError-gmagError), 0.01)
# and that we got an array of EBV values for the milky way line of sight extinction
ebvmin = 0
ebvmax = 2
ebvstep = (ebvmax - ebvmin)/float(len(galaxykeys))
ebv_mw = n.arange(ebvmin, ebvmax, ebvstep)

# and that we have a range of values for redshift
redshiftmin = 0.5
redshiftmax = 1.5
redshiftstep = (redshiftmax - redshiftmin)/float(len(galaxykeys))
redshifts = n.arange(redshiftmin, redshiftmax, redshiftstep)

# okay, instantiate the bandpass used to calculate the magnitude 
rband = Bandpass()
rband.readThroughput("exampleBandpass.dat")

# instantiate gals into dictionary
gals = {}
rootdir = "./"
for key in galaxykeys:
    gals[key] = Sed()
    gals[key].readSED_flambda(rootdir + key)

# we know the gals have the same wavelength array (gals[i].wavelen)
# (because they were the same SED!)  BUT, in general we may not know this is true.
# so check .. (this is not strictly necessary, but does speed up some of the calculations
#  below. so, for many gals, do it.). For GALAXIES we want to be sure to base this on
# a wide enough range, so use a galaxy that is good for the wavelen_base.

wavelen_base = gals[key].wavelen
def run_lsst_baker(redshift_grid):
    """
    Accepts a redshift grid (a numpy array).  Reads in all of the SEDs from
    ../data/sed/ and the calculates their colors in all of the lsst bands,
    given those redshifts

    Returns a structured numpy array containing
    sedname
    redshift
    ug
    gr
    ri
    iz
    zy
    time (the time spent calculating the magnitudes)
    """
    bandpass_dir = os.path.join('..', 'data', 'bandpass')
    bandpass_list = []
    for bp_name in ('total_u.dat', 'total_g.dat', 'total_r.dat', 'total_i.dat',
                    'total_z.dat', 'total_y.dat'):

        bp = Bandpass()
        bp.readThroughput(os.path.join(bandpass_dir, bp_name))
        bandpass_list.append(bp)

    sed_dir = os.path.join('..', 'data', 'sed')
    list_of_sed_names = sorted([nn for nn in os.listdir(sed_dir)
                                if 'spec' in nn and 'ang' not in nn])

    n_rows = len(list_of_sed_names)*len(redshift_grid)
    dtype = np.dtype([('sedname', str, 300), ('redshift', np.float),
                      ('ug', np.float), ('gr', np.float), ('ri', np.float),
                      ('iz', np.float), ('zy', np.float), ('time', np.float)])

    dummy = ('aaaa', 1.0, 1, 1, 1, 1, 1, 1.0)
    output_array = np.array([dummy]*n_rows, dtype=dtype)

    i_row = 0
    for redshift in redshift_grid:
        for sed_name in list_of_sed_names:
            ss = Sed()
#            t_start = time.clock()
            t_start = time.time()
            ss.readSED_flambda(os.path.join(sed_dir, sed_name))
            ss.redshiftSED(redshift)
            local_list = []
            for bp in bandpass_list:
                mm = ss.calcMag(bp)
                local_list.append(mm)
            #print local_list[0], local_list[1], local_list[0]-local_list[1]
#            time_spent = time.clock()-t_start
            time_spent = time.time()-t_start
            output_array[i_row][0] = sed_name
            output_array[i_row][1] = redshift
            output_array[i_row][2] = local_list[0]-local_list[1]
            output_array[i_row][3] = local_list[1]-local_list[2]
            output_array[i_row][4] = local_list[2]-local_list[3]
            output_array[i_row][5] = local_list[3]-local_list[4]
            output_array[i_row][6] = local_list[4]-local_list[5]
            output_array[i_row][7] = time_spent
            i_row += 1

    return output_array
Exemplo n.º 52
0
import os
import glob
import numpy as np
import matplotlib.pyplot as plt
from lsst.sims.photUtils import Bandpass, Sed

filterdir = os.getenv('LSST_THROUGHPUTS_BASELINE')
filterlist = ('u', 'g', 'r', 'i', 'z', 'y')

lsst = {}
for f  in filterlist:
    lsst[f] = Bandpass()
    lsst[f].readThroughput(os.path.join(filterdir, 'total_' + f + '.dat'))
harrisV = Bandpass()
harrisV.readThroughput('harris_V.dat')

seds = glob.glob('*.dat')
seds.remove('harris_V.dat')

print 'Calculating colors for seds: \n', seds

writestring = 'Sed '
for f in filterlist:
    writestring += 'V-%s ' %(f)
print writestring


fig = plt.figure()
for s in seds:
    sed = Sed()
Exemplo n.º 53
0
        # read in the filter throughput and multiply the existing throughputs
        # by that curve
        np_filter = np.genfromtxt(os.path.join(bp_dir,
                                               'filter_%s.dat' % bp_name),
                                  dtype=throughput_dtype)

        for np_component in np_component_list:
            interped_throughput = np.interp(np_filter['wav_nm'],
                                            np_component['wav_nm'],
                                            np_component['throughput'])

            np_filter['throughput'] *= interped_throughput

        if _LSST_STACK_INSTALLED:
            filter_bp = Bandpass()
            filter_bp.readThroughput(
                os.path.join(bp_dir, 'filter_%s.dat' % bp_name))

            wav, sb = optics_bp.multiplyThroughputs(filter_bp.wavelen,
                                                    filter_bp.sb)
            bp = Bandpass(wavelen=wav, sb=sb)

        # integrate the SED over the total system throughput
        flambda = np.interp(np_filter['wav_nm'], np_sed['wav_nm'],
                            np_sed['flambda'])
        phys_params = PhysicalParameters()
        phot = flambda * np_filter['wav_nm'] / (phys_params.planck *
                                                phys_params.lightspeed * 1.0e9)

        integral = 0.5 * (
            (phot[1:] * np_filter['throughput'][1:] +
             phot[:-1] * np_filter['throughput'][:-1]) *
    def testObjectPlacement(self):
        """
        Test that GalSim places objects on the correct pixel by drawing
        images, reading them in, and then comparing the flux contained in
        circles of 2 fwhm radii about the object's expected positions with
        the actual expected flux of the objects.
        """
        scratchDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'scratchSpace')
        catName = os.path.join(scratchDir, 'placementCatalog.dat')
        imageRoot = os.path.join(scratchDir, 'placementImage')
        dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat')

        cameraDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData')
        camera = ReturnCamera(cameraDir)
        detector = camera[0]
        imageName = '%s_%s_u.fits' % (imageRoot, detector.getName())

        controlSed = Sed()
        controlSed.readSED_flambda(
                                   os.path.join(getPackageDir('sims_sed_library'),
                                               'flatSED','sed_flat.txt.gz')
                                   )

        uBandpass = Bandpass()
        uBandpass.readThroughput(
                                 os.path.join(getPackageDir('throughputs'),
                                              'baseline','total_u.dat')
                                )

        controlBandpass = Bandpass()
        controlBandpass.imsimBandpass()

        ff = controlSed.calcFluxNorm(self.magNorm, uBandpass)
        controlSed.multiplyFluxNorm(ff)
        a_int, b_int = controlSed.setupCCMab()
        controlSed.addCCMDust(a_int, b_int, A_v=0.1, R_v=3.1)

        nSamples = 5
        numpy.random.seed(42)
        pointingRaList = numpy.random.random_sample(nSamples)*360.0
        pointingDecList = numpy.random.random_sample(nSamples)*180.0 - 90.0
        rotSkyPosList = numpy.random.random_sample(nSamples)*360.0
        fwhmList = numpy.random.random_sample(nSamples)*1.0 + 0.3

        actualCounts = None

        for pointingRA, pointingDec, rotSkyPos, fwhm in \
        zip(pointingRaList, pointingDecList, rotSkyPosList, fwhmList):


            obs = ObservationMetaData(unrefractedRA=pointingRA,
                                      unrefractedDec=pointingDec,
                                      boundType='circle',
                                      boundLength=4.0,
                                      mjd=49250.0,
                                      rotSkyPos=rotSkyPos)

            xDisplacementList = numpy.random.random_sample(nSamples)*60.0-30.0
            yDisplacementList = numpy.random.random_sample(nSamples)*60.0-30.0
            create_text_catalog(obs, dbFileName, xDisplacementList, yDisplacementList,
                                mag_norm=[self.magNorm]*len(xDisplacementList))
            db = placementFileDBObj(dbFileName, runtable='test')
            cat = placementCatalog(db, obs_metadata=obs)
            if actualCounts is None:
                actualCounts = controlSed.calcADU(uBandpass, cat.photParams)

            psf = SNRdocumentPSF(fwhm=fwhm)
            cat.setPSF(psf)
            cat.camera = camera

            cat.write_catalog(catName)
            cat.write_images(nameRoot=imageRoot)

            objRaList = []
            objDecList = []
            with open(catName, 'r') as inFile:
                for line in inFile:
                    if line[0] != '#':
                        words = line.split(';')
                        objRaList.append(numpy.radians(numpy.float(words[2])))
                        objDecList.append(numpy.radians(numpy.float(words[3])))

            objRaList = numpy.array(objRaList)
            objDecList = numpy.array(objDecList)

            self.check_placement(imageName, objRaList, objDecList,
                                [fwhm]*len(objRaList),
                                numpy.array([actualCounts]*len(objRaList)),
                                cat.photParams.gain, detector, camera, obs, epoch=2000.0)

            if os.path.exists(dbFileName):
                os.unlink(dbFileName)
            if os.path.exists(catName):
                os.unlink(catName)
            if os.path.exists(imageName):
                os.unlink(imageName)
Exemplo n.º 55
0
    def testAlternateNormalizingBandpass(self):
        """
        A reiteration of testAddingToList, but testing with a non-imsimBandpass
        normalizing bandpass
        """
        normalizingBand = Bandpass()
        normalizingBand.readThroughput(os.path.join(getPackageDir('throughputs'), 'baseline', 'total_r.dat'))
        nSed = 10
        sedNameList_0 = self.getListOfSedNames(nSed)
        magNormList_0 = self.rng.random_sample(nSed)*5.0 + 15.0
        internalAvList_0 = self.rng.random_sample(nSed)*0.3 + 0.1
        redshiftList_0 = self.rng.random_sample(nSed)*5.0
        galacticAvList_0 = self.rng.random_sample(nSed)*0.3 + 0.1
        wavelen_match = np.arange(300.0, 1500.0, 10.0)
        testList = SedList(sedNameList_0, magNormList_0,
                           fileDir=self.sedDir,
                           normalizingBandpass=normalizingBand,
                           internalAvList=internalAvList_0,
                           redshiftList=redshiftList_0, galacticAvList=galacticAvList_0,
                           wavelenMatch=wavelen_match)

        sedNameList_1 = self.getListOfSedNames(nSed)
        magNormList_1 = self.rng.random_sample(nSed)*5.0 + 15.0

        internalAvList_1 = self.rng.random_sample(nSed)*0.3 + 0.1

        redshiftList_1 = self.rng.random_sample(nSed)*5.0

        galacticAvList_1 = self.rng.random_sample(nSed)*0.3 + 0.1

        testList.loadSedsFromList(sedNameList_1, magNormList_1,
                                  internalAvList=internalAvList_1,
                                  galacticAvList=galacticAvList_1,
                                  redshiftList=redshiftList_1)

        self.assertEqual(len(testList), 2*nSed)
        np.testing.assert_array_equal(wavelen_match, testList.wavelenMatch)

        for ix in range(len(sedNameList_0)):
            self.assertAlmostEqual(internalAvList_0[ix], testList.internalAvList[ix], 10)
            self.assertAlmostEqual(galacticAvList_0[ix], testList.galacticAvList[ix], 10)
            self.assertAlmostEqual(redshiftList_0[ix], testList.redshiftList[ix], 10)

        for ix in range(len(sedNameList_1)):
            self.assertAlmostEqual(internalAvList_1[ix], testList.internalAvList[ix+nSed], 10)
            self.assertAlmostEqual(galacticAvList_1[ix], testList.galacticAvList[ix+nSed], 10)
            self.assertAlmostEqual(redshiftList_1[ix], testList.redshiftList[ix+nSed], 10)

        for ix, (name, norm, iav, gav, zz) in \
            enumerate(zip(sedNameList_0, magNormList_0, internalAvList_0,
                      galacticAvList_0, redshiftList_0)):

            sedControl = Sed()
            sedControl.readSED_flambda(os.path.join(self.sedDir, name+'.gz'))

            fnorm = sedControl.calcFluxNorm(norm, normalizingBand)
            sedControl.multiplyFluxNorm(fnorm)

            a_coeff, b_coeff = sedControl.setupCCM_ab()
            sedControl.addDust(a_coeff, b_coeff, A_v=iav)

            sedControl.redshiftSED(zz, dimming=True)
            sedControl.resampleSED(wavelen_match=wavelen_match)

            a_coeff, b_coeff = sedControl.setupCCM_ab()
            sedControl.addDust(a_coeff, b_coeff, A_v=gav)

            sedTest = testList[ix]

            np.testing.assert_array_equal(sedControl.wavelen, sedTest.wavelen)
            np.testing.assert_array_equal(sedControl.flambda, sedTest.flambda)
            np.testing.assert_array_equal(sedControl.fnu, sedTest.fnu)

        for ix, (name, norm, iav, gav, zz) in \
            enumerate(zip(sedNameList_1, magNormList_1, internalAvList_1,
                          galacticAvList_1, redshiftList_1)):

            sedControl = Sed()
            sedControl.readSED_flambda(os.path.join(self.sedDir, name+'.gz'))

            fnorm = sedControl.calcFluxNorm(norm, normalizingBand)
            sedControl.multiplyFluxNorm(fnorm)

            a_coeff, b_coeff = sedControl.setupCCM_ab()
            sedControl.addDust(a_coeff, b_coeff, A_v=iav)

            sedControl.redshiftSED(zz, dimming=True)

            sedControl.resampleSED(wavelen_match=wavelen_match)

            a_coeff, b_coeff = sedControl.setupCCM_ab()
            sedControl.addDust(a_coeff, b_coeff, A_v=gav)

            sedTest = testList[ix+nSed]

            np.testing.assert_array_equal(sedControl.wavelen, sedTest.wavelen)
            np.testing.assert_array_equal(sedControl.flambda, sedTest.flambda)
            np.testing.assert_array_equal(sedControl.fnu, sedTest.fnu)
Exemplo n.º 56
0
class BaseObs(object):
    """
    Base class to generate observations of a set of moving objects.
    
    Parameters
    ----------
    cameraFootprint : CameraFootprint, opt
        A cameraFootprint class (which provides a way to determine if observations fall into a given
        camera footprint), such as lsstCameraFootprint. 
        If none provided, a simple circular FOV is available from the BaseObs class.
    rFov : float, opt
        Radius of the fov, to use for a circular FOV if cameraFootprint is None, in degrees.
        Default 1.75 degrees.
    """
    def __init__(self,
                 cameraFootprint=None,
                 rFov=1.75,
                 timeCol='observationStartMJD',
                 seeingCol='seeingFwhmGeom',
                 visitExpTimeCol='visitExposureTime'):
        self.cameraFootprint = cameraFootprint
        self.rFov = rFov
        self.timeCol = timeCol
        self.seeingCol = seeingCol
        self.visitExpTimeCol = visitExpTimeCol
        self.colors = {}

    def setOrbits(self, orbitObj):
        if isinstance(orbitObj, Orbits):
            self.orbits = orbitObj
        else:
            raise ValueError(
                'Expected an lsst.sims.movingObjects.Orbit object.')

    def calcTrailingLosses(self, velocity, seeing, texp=30.):
        """Calculate the detection and SNR traiiling losses.

        Parameters
        ----------
        velocity : np.ndarray or float
            The velocity of the moving objects, in deg/day.
        seeing : np.ndarray or float
            The seeing of the images, in arcseconds.
        texp : np.ndarray or float, opt
            The exposure time of the images, in seconds. Default 30.

        Returns
        -------
        (np.ndarray, np.ndarray) or (float, float)
            dmagTrail and dmagDetect for each set of velocity/seeing/texp values.
        """
        a_trail = 0.761
        b_trail = 1.162
        a_det = 0.420
        b_det = 0.003
        x = velocity * texp / seeing / 24.0
        dmagTrail = 1.25 * np.log10(1 + a_trail * x**2 / (1 + b_trail * x))
        dmagDetect = 1.25 * np.log10(1 + a_det * x**2 / (1 + b_det * x))
        return (dmagTrail, dmagDetect)

    def readFilters(self,
                    filterDir=None,
                    bandpassRoot='total_',
                    bandpassSuffix='.dat',
                    filterlist=('u', 'g', 'r', 'i', 'z', 'y'),
                    vDir=None,
                    vFilter='harris_V.dat'):
        """
        Read (LSST) and Harris (V) filters. 
        
        Only the defaults are LSST specific; this can easily be adapted for any survey. 

        Parameters
        ----------
        filterDir : str, opt
            Directory containing the filter throughput curves ('total_*.dat')
            Default set by 'LSST_THROUGHPUTS_BASELINE' env variable.
        bandpassRoot : str, opt
            Rootname of the throughput curves in filterlist. 
            E.g. throughput curve names are bandpassRoot + filterlist[i] + bandpassSuffix
            Default 'total_' (appropriate for LSST throughput repo).
        bandpassSuffix : str, opt
            Suffix for the throughput curves in filterlist.
            Default '.dat' (appropriate for LSST throughput repo).
        filterlist : list, opt
            List containing the filter names to use to calculate colors.
            Default ('u', 'g', 'r', 'i', 'z', 'y')
        vDir : str, opt
            Directory containing the V band throughput curve.
            Default None = $SIMS_MOVINGOBJECTS_DIR/data.
        vFilter : str, opt
            Name of the V band filter curve. 
            Default harris_V.dat.
        """
        if filterDir is None:
            filterDir = os.getenv('LSST_THROUGHPUTS_BASELINE')
        if filterDir is None:
            raise ValueError(
                'Please set filterDir or env variable LSST_THROUGHPUTS_BASELINE'
            )
        if vDir is None:
            vDir = os.path.join(getPackageDir('SIMS_MOVINGOBJECTS'), 'data')
        self.filterlist = filterlist
        # Read filter throughput curves from disk.
        self.lsst = {}
        for f in self.filterlist:
            self.lsst[f] = Bandpass()
            self.lsst[f].readThroughput(
                os.path.join(filterDir, bandpassRoot + f + bandpassSuffix))
        self.vband = Bandpass()
        self.vband.readThroughput(os.path.join(vDir, vFilter))

    def calcColors(self, sedname='C.dat', sedDir=None):
        """Calculate the colors for a given SED.

        If the sedname is not already in the dictionary self.colors, this reads the
        SED from disk and calculates all V-[filter] colors for all filters in self.filterlist.
        The result is stored in self.colors[sedname][filter].

        Parameters
        ----------
        sedname : str (opt)
            Name of the SED. Default 'C.dat'.
        sedDir : str (opt)
            Directory containing the SEDs of the moving objects.
            Default None = $SIMS_MOVINGOBJECTS_DIR/data.

        Returns
        -------
        dict
            Dictionary of the colors in self.filterlist for this particular Sed.
        """
        if sedname not in self.colors:
            if sedDir is None:
                sedDir = os.path.join(getPackageDir('SIMS_MOVINGOBJECTS'),
                                      'data')
            moSed = Sed()
            moSed.readSED_flambda(os.path.join(sedDir, sedname))
            vmag = moSed.calcMag(self.vband)
            self.colors[sedname] = {}
            for f in self.filterlist:
                self.colors[sedname][f] = moSed.calcMag(self.lsst[f]) - vmag
        return self.colors[sedname]

    def ssoInCircleFov(self, ephems, obsData, rFov=2.1):
        """Determine which observations are within a circular fov for a series of observations.

        Parameters
        ----------
        ephems : np.recarray
            Ephemerides for the objects, with RA and Dec as 'ra' and 'dec' columns (in degrees).
        obsData : np.recarray
            The observation pointings, with RA and Dec as 'ra' and 'dec' columns (in degrees).
        rFov : float, opt
            The radius of the field of view, in degrees.
            Default 2.1 is appropriate for LSST fov if later applying camera footprint.
            A value of 1.75 would be appropriate for simple circular LSST FOV assumption.

        Returns
        -------
        np.ndarray
            Returns the indexes of the numpy array of the object observations which are inside the fov.
        """
        sep = angularSeparation(ephems['ra'], ephems['dec'], obsData['ra'],
                                obsData['dec'])
        idxObs = np.where(sep <= rFov)[0]
        return idxObs

    # Put together the output.
    def _openOutput(self, outfileName):
        # Make sure the directory exists to write the output file into.
        outDir = os.path.split(outfileName)[0]
        if len(outDir) > 0:
            if not os.path.isdir(outDir):
                os.makedirs(outDir)
        # Open the output file for writing.
        self.outfile = open(outfileName, 'w')
        self.wroteHeader = False

    def writeObs(self,
                 objId,
                 objEphs,
                 obsData,
                 outfileName='out.txt',
                 sedname='C.dat'):
        """
        Call for each object; write out the observations of each object.
        """
        # Return if there's nothing to write out.
        if len(objEphs) == 0:
            return
        # Open file if needed.
        try:
            self.outfile
        except AttributeError:
            self._openOutput(outfileName)
        # Calculate the extra columns we want to write out
        # (dmag due to color, trailing loss, and detection loss)
        # First calculate and match the color dmag term.
        dmagColor = np.zeros(len(obsData), float)
        dmagColorDict = self.calcColors(sedname)
        filterlist = np.unique(obsData['filter'])
        for f in filterlist:
            if f not in dmagColorDict:
                raise UserWarning(
                    'Could not find filter %s in calculated colors!' % (f))
            match = np.where(obsData['filter'] == f)[0]
            dmagColor[match] = dmagColorDict[f]
        magFilter = objEphs['magV'] + dmagColor
        # Calculate trailing and detection loses.
        dmagTrail, dmagDetect = self.calcTrailingLosses(
            objEphs['velocity'], obsData[self.seeingCol],
            obsData[self.visitExpTimeCol])
        # Turn into a recarray so it's easier below.
        dmags = np.rec.fromarrays(
            [magFilter, dmagColor, dmagTrail, dmagDetect],
            names=['magFilter', 'dmagColor', 'dmagTrail', 'dmagDetect'])

        outCols = [
            'objId',
        ] + list(objEphs.dtype.names) + list(obsData.dtype.names) + list(
            dmags.dtype.names)

        if not self.wroteHeader:
            writestring = ''
            for col in outCols:
                writestring += '%s ' % (col)
            self.outfile.write('%s\n' % (writestring))
            self.wroteHeader = True

        # Write results.
        for eph, simdat, dm in zip(objEphs, obsData, dmags):
            writestring = '%s ' % (objId)
            for col in eph.dtype.names:
                writestring += '%s ' % (eph[col])
            for col in simdat.dtype.names:
                writestring += '%s ' % (simdat[col])
            for col in dm.dtype.names:
                writestring += '%s ' % (dm[col])
            self.outfile.write('%s\n' % (writestring))
        self.outfile.flush()