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)
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
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"]
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 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)
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
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
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
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
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
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
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
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)
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
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)
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
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
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
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
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)
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']
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 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)
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)
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)
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']
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]
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]
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)
'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)
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
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()
# 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)
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)
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()