def calcEffWavelen(hardware, title, throughputDir=None): photParams = PhotometricParameters() lsstDefaults = LSSTdefaults() atmos = {} stdAtmoFile = os.path.join(os.getenv('SYSENG_THROUGHPUTS_DIR'), 'siteProperties/pachonModtranAtm_12.dat') atmos['std'] = Bandpass() atmos['std'].readThroughput(stdAtmoFile) multiAtmos = False if throughputDir is None: throughputDir = os.getenv('THROUGHPUTS_DIR') if throughputDir is not None: multiAtmos = True Xarr = np.arange(1.0, 2.55, 0.1) for X in Xarr: atmos['%.1f' %X] = Bandpass() atmos['%.1f' %X].readThroughput(os.path.join(throughputDir, 'atmos/atmos_%d.dat' %(int(X*10)))) atmoskeys = sorted(atmos.keys()) print title print ' %s' %(' '.join(atmoskeys)) system = Bandpass() effsb = {} for f in ['u', 'g', 'r', 'i', 'z', 'y']: writestring = '%s ' %f for k in atmoskeys: system.wavelen, system.sb = hardware[f].multiplyThroughputs(atmos[k].wavelen, atmos[k].sb) effphi, effsb[k] = system.calcEffWavelen() writestring += '%.2f ' %(effsb[k]) print writestring
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 testMags(self): """ Test that the interpolated mags are similar to mags computed from interpolated spectra """ throughPath = os.path.join(getPackageDir("throughputs"), "baseline") filters = ["u", "g", "r", "i", "z", "y"] bps = [] for filterName in filters: bp = np.loadtxt( os.path.join(throughPath, "filter_%s.dat" % filterName), dtype=zip(["wave", "trans"], [float] * 2) ) lsst_bp = Bandpass() lsst_bp.setBandpass(bp["wave"], bp["trans"]) bps.append(lsst_bp) sm1 = sb.SkyModel() sm1.setRaDecMjd([36.0], [-68.0], 49353.18, degrees=True) sm1.computeSpec() mags1 = [] for bp in bps: mags1.append(sm1.computeMags(bandpass=bp)) mags1 = np.array(mags1) sm2 = sb.SkyModel(mags=True) sm2.setRaDecMjd([36.0], [-68.0], 49353.18, degrees=True) sm2.computeSpec() mag2 = sm2.computeMags() np.testing.assert_allclose(mags1, mag2.T, rtol=1e-4)
def testMags(self): """ Test that the interpolated mags are similar to mags computed from interpolated spectra """ throughPath = os.path.join(getPackageDir('throughputs'),'baseline') filters = ['u','g','r','i','z','y'] bps = [] for filterName in filters: bp = np.loadtxt(os.path.join(throughPath, 'filter_%s.dat' % filterName), dtype=zip(['wave','trans'],[float]*2 )) lsst_bp = Bandpass() lsst_bp.setBandpass(bp['wave'], bp['trans']) bps.append(lsst_bp) sm1 = sb.SkyModel() sm1.setRaDecMjd([36.],[-68.],49353.18, degrees=True) sm1.computeSpec() mags1 = [] for bp in bps: mags1.append(sm1.computeMags(bandpass=bp)) mags1 = np.array(mags1) sm2 = sb.SkyModel(mags=True) sm2.setRaDecMjd([36.],[-68.],49353.18, degrees=True) sm2.computeSpec() mag2 = sm2.computeMags() np.testing.assert_allclose(mags1,mag2.T, rtol=1e-4)
def __init__(self, m5Col='fiveSigmaDepth', metricName='ExgalM5', units='mag', lsstFilter='r', wavelen_min=None , wavelen_max=None , **kwargs): # Set the name for the dust map to use. This is gathered into the MetricBundle. maps = ['DustMap'] # Set the default wavelength limits for the lsst filters. These are approximately correct. waveMins = {'u':330.,'g':403.,'r':552.,'i':691.,'z':818.,'y':950.} waveMaxes = {'u':403.,'g':552.,'r':691.,'i':818.,'z':922.,'y':1070.} if lsstFilter is not None: wavelen_min = waveMins[lsstFilter] wavelen_max = waveMaxes[lsstFilter] self.m5Col = m5Col super().__init__(col=[self.m5Col], maps=maps, metricName=metricName, units=units, **kwargs) # Set up internal values for the dust extinction. testsed = Sed() testsed.setFlatSED(wavelen_min=wavelen_min, wavelen_max=wavelen_max, wavelen_step=1.0) testbandpass = Bandpass(wavelen_min=wavelen_min, wavelen_max=wavelen_max, wavelen_step=1.0) testbandpass.setBandpass(wavelen=testsed.wavelen, sb=np.ones(len(testsed.wavelen))) self.R_v = 3.1 self.ref_ebv = 1.0 # Calculate non-dust-extincted magnitude flatmag = testsed.calcMag(testbandpass) # Add dust self.a, self.b = testsed.setupCCM_ab() testsed.addDust(self.a, self.b, ebv=self.ref_ebv, R_v=self.R_v) # Calculate difference due to dust when EBV=1.0 (m_dust = m_nodust - Ax, Ax > 0) self.Ax1 = testsed.calcMag(testbandpass) - flatmag # We will call Coaddm5Metric to calculate the coadded depth. Set it up here. self.Coaddm5Metric = Coaddm5Metric(m5Col=m5Col)
def testMags(self): """ Test that the interpolated mags are similar to mags computed from interpolated spectra """ throughPath = os.path.join(getPackageDir('throughputs'), 'baseline') filters = ['u', 'g', 'r', 'i', 'z', 'y'] bps = [] for filterName in filters: bp = np.loadtxt(os.path.join(throughPath, 'filter_%s.dat' % filterName), dtype=zip(['wave', 'trans'], [float]*2)) lsst_bp = Bandpass() lsst_bp.setBandpass(bp['wave'], bp['trans']) bps.append(lsst_bp) sm1 = self.sm_spec sm1.setRaDecMjd([36.], [-68.], 49353.18, degrees=True) mags1 = [] for bp in bps: mags1.append(sm1.returnMags(bandpass=bp)) mags1 = np.array(mags1) sm2 = self.sm_mags sm2.setRaDecMjd([36.], [-68.], 49353.18, degrees=True) mag2 = sm2.returnMags() for i, filtername in enumerate(filters): np.testing.assert_allclose(mags1[i, :], mag2[filtername], rtol=1e-4)
def test_norm(self): """ Test that the special test case getImsimFluxNorm returns the same value as calling calcFluxNorm actually passing in the imsim Bandpass """ bp = Bandpass() bp.imsimBandpass() rng = np.random.RandomState(1123) wavelen = np.arange(300.0, 2000.0, 0.17) for ix in range(10): flux = rng.random_sample(len(wavelen))*100.0 sed = Sed() sed.setSED(wavelen=wavelen, flambda=flux) magmatch = rng.random_sample()*5.0 + 10.0 control = sed.calcFluxNorm(magmatch, bp) test = getImsimFluxNorm(sed, magmatch) # something about how interpolation is done in Sed means # that the values don't come out exactly equal. They come # out equal to 8 seignificant digits, though. self.assertEqual(control, test)
def testStellarPhotometricUncertainties(self): """ Test in the case of a catalog of stars """ lsstDefaults = LSSTdefaults() starDB = testStarsDBObj(driver=self.driver, host=self.host, database=self.dbName) starCat = testStarCatalog(starDB, obs_metadata=self.obs_metadata) phot = PhotometryStars() ct = 0 for line in starCat.iter_catalog(): starSed = Sed() starSed.readSED_flambda(os.path.join(lsst.utils.getPackageDir('sims_sed_library'), defaultSpecMap[line[14]])) imsimband = Bandpass() imsimband.imsimBandpass() fNorm = starSed.calcFluxNorm(line[15], imsimband) starSed.multiplyFluxNorm(fNorm) aV = numpy.float(line[16]) a_int, b_int = starSed.setupCCMab() starSed.addCCMDust(a_int, b_int, A_v=aV) for i in range(len(self.bandpasses)): controlSigma = calcMagError_sed(starSed, self.totalBandpasses[i], self.skySeds[i], self.hardwareBandpasses[i], FWHMeff=lsstDefaults.FWHMeff(self.bandpasses[i]), photParams=PhotometricParameters()) testSigma = line[8+i] self.assertAlmostEqual(controlSigma, testSigma, 4) ct += 1 self.assertGreater(ct, 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)
def testMags(self): """ Test that the interpolated mags are similar to mags computed from interpolated spectra """ throughPath = os.path.join(getPackageDir('throughputs'), 'baseline') filters = ['u', 'g', 'r', 'i', 'z', 'y'] bps = {} for filterName in filters: bp = np.loadtxt(os.path.join(throughPath, 'filter_%s.dat' % filterName), dtype=list(zip(['wave', 'trans'], [float] * 2))) lsst_bp = Bandpass() lsst_bp.setBandpass(bp['wave'], bp['trans']) bps[filterName] = lsst_bp sm1 = self.sm_spec sm1.setRaDecMjd([36.], [-68.], 49353.18, degrees=True) mags1 = sm1.returnMags(bandpasses=bps) sm2 = self.sm_mags sm2.setRaDecMjd([36.], [-68.], 49353.18, degrees=True) mag2 = sm2.returnMags() for i, filtername in enumerate(filters): np.testing.assert_allclose(mags1[filtername], mag2[filtername], rtol=1e-4)
def test_norm(self): """ Test that the special test case getImsimFluxNorm returns the same value as calling calcFluxNorm actually passing in the imsim Bandpass """ bp = Bandpass() bp.imsimBandpass() rng = np.random.RandomState(1123) wavelen = np.arange(300.0, 2000.0, 0.17) for ix in range(10): flux = rng.random_sample(len(wavelen)) * 100.0 sed = Sed() sed.setSED(wavelen=wavelen, flambda=flux) magmatch = rng.random_sample() * 5.0 + 10.0 control = sed.calcFluxNorm(magmatch, bp) test = getImsimFluxNorm(sed, magmatch) # something about how interpolation is done in Sed means # that the values don't come out exactly equal. They come # out equal to 8 seignificant digits, though. self.assertEqual(control, test)
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 get_phosimVars(self): """ Obtain variables sedFilepath to be used to obtain unique filenames for each SED for phoSim and MagNorm which is also used. Note that aside from acting as a getter, this also writes spectra to `self.sn_sedfile_prefix`snid_mjd_band.dat for each observation of interest """ # construct the unique filename # method: snid_mjd(to 4 places of decimal)_bandpassname mjd = "_{:0.4f}_".format(self.mjdobs) mjd += self.obs_metadata.bandpass + '.dat' fnames = np.array([ self.sn_sedfile_prefix + str(int(elem)) + mjd if isinstance( elem, numbers.Number) else self.sn_sedfile_prefix + str(elem) + mjd for elem in self.column_by_name('snid') ], dtype='str') c, x1, x0, t0, z = self.column_by_name('c'),\ self.column_by_name('x1'),\ self.column_by_name('x0'),\ self.column_by_name('t0'),\ self.column_by_name('redshift') bp = Bandpass() bp.imsimBandpass() magNorms = np.zeros(len(fnames)) snobject = SNObject() snobject.rectifySED = True for i in range(len(self.column_by_name('snid'))): # if t0 is nan, this was set by the catalog for dim SN, or SN # outside redshift range, We will not provide a SED file for these if np.isnan(t0[i]): magNorms[i] = np.nan fnames[i] = None else: snobject.set(c=c[i], x1=x1[i], x0=x0[i], t0=t0[i], z=z[i]) if snobject.modelOutSideTemporalRange == 'zero': if self.mjdobs > snobject.maxtime( ) or self.mjdobs < snobject.mintime(): magNorms[i] = np.nan fnames[i] = None # SED in rest frame sed = snobject.SNObjectSourceSED(time=self.mjdobs) try: magNorms[i] = sed.calcMag(bandpass=bp) except: # sed.flambda = 1.0e-20 magNorms[i] = 1000. # sed.calcMag(bandpass=bp) if self.writeSedFile: sed.writeSED(fnames[i]) return (fnames, magNorms)
def _create_library_one_sed(_galaxy_sed_dir, sed_file_name_list, av_grid, rv_grid, bandpass_dict, out_dict, out_lock): n_obj = 0 for i_av, av in enumerate(av_grid): for i_rv, rv in enumerate(rv_grid): if av < 0.01 and i_rv > 0: continue n_obj += 1 imsim_bp = Bandpass() imsim_bp.imsimBandpass() t_start = time.time() sed_names_out = [] rv_out_list_out = [] av_out_list_out = [] sed_mag_norm_out = [] sed_mag_list_out = [] for i_sed, sed_file_name in enumerate(sed_file_name_list): base_spec = Sed() base_spec.readSED_flambda(os.path.join(_galaxy_sed_dir, sed_file_name)) ax, bx = base_spec.setupCCM_ab() mag_norm = base_spec.calcMag(imsim_bp) sed_names = np.array([defaultSpecMap[sed_file_name]] * n_obj) rv_out_list = np.zeros(n_obj, dtype=float) av_out_list = np.zeros(n_obj, dtype=float) sed_mag_norm = mag_norm * np.ones(n_obj, dtype=float) sed_mag_list = np.zeros((n_obj, len(bandpass_dict)), dtype=float) i_obj = 0 for i_av, av in enumerate(av_grid): for i_rv, rv in enumerate(rv_grid): if av < 0.01 and i_rv > 0: continue spec = Sed(wavelen=base_spec.wavelen, flambda=base_spec.flambda) spec.addDust(ax, bx, A_v=av, R_v=rv) av_out_list[i_obj] = av rv_out_list[i_obj] = rv sed_mag_list[i_obj][:] = bandpass_dict.magListForSed(spec) i_obj += 1 sed_names_out.append(sed_names) sed_mag_norm_out.append(sed_mag_norm) sed_mag_list_out.append(sed_mag_list) av_out_list_out.append(av_out_list) rv_out_list_out.append(rv_out_list) with out_lock: out_dict['sed_names'] += sed_names_out out_dict['sed_mag_norm'] += sed_mag_norm_out out_dict['sed_mag_list'] += sed_mag_list_out out_dict['av_out_list'] += av_out_list_out out_dict['rv_out_list'] += rv_out_list_out
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 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 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 calcMagNorm(self, objectMags, sedObj, bandpassDict, mag_error=None, redshift=None, filtRange=None): """ This will find the magNorm value that gives the closest match to the magnitudes of the object using the matched SED. Uses scipy.optimize.leastsq to find the values of fluxNorm that minimizes the function: ((flux_obs - (fluxNorm*flux_model))/flux_error)**2. @param [in] objectMags are the magnitude values for the object with extinction matching that of the SED object. In the normal case using the selectSED routines above it will be dereddened mags. @param [in] sedObj is an Sed class instance that is set with the wavelength and flux of the matched SED @param [in] bandpassDict is a BandpassDict class instance with the Bandpasses set to those for the magnitudes given for the catalog object @param [in] mag_error are provided error values for magnitudes in objectMags. If none provided then this defaults to 1.0. This should be an array of the same length as objectMags. @param [in] redshift is the redshift of the object if the magnitude is observed @param [in] filtRange is a selected range of filters specified by their indices in the bandpassList to match up against. Used when missing data in some magnitude bands. @param [out] bestMagNorm is the magnitude normalization for the given magnitudes and SED """ import scipy.optimize as opt sedTest = Sed() sedTest.setSED(sedObj.wavelen, flambda=sedObj.flambda) if redshift is not None: sedTest.redshiftSED(redshift) imSimBand = Bandpass() imSimBand.imsimBandpass() zp = -2.5 * np.log10(3631) #Note using default AB zeropoint flux_obs = np.power(10, (objectMags + zp) / (-2.5)) sedTest.resampleSED(wavelen_match=bandpassDict.wavelenMatch) sedTest.flambdaTofnu() flux_model = sedTest.manyFluxCalc(bandpassDict.phiArray, bandpassDict.wavelenStep) if filtRange is not None: flux_obs = flux_obs[filtRange] flux_model = flux_model[filtRange] if mag_error is None: flux_error = np.ones(len(flux_obs)) else: flux_error = np.abs(flux_obs * (np.log(10) / (-2.5)) * mag_error) bestFluxNorm = opt.leastsq( lambda x: ((flux_obs - (x * flux_model)) / flux_error), 1.0)[0][0] sedTest.multiplyFluxNorm(bestFluxNorm) bestMagNorm = sedTest.calcMag(imSimBand) return bestMagNorm
def _get_sed_mags_and_cosmology(catalog_name): """ Returns 3 numpy arrays: sed_names, sed_mag_list, sed_mag_norm and a dictionary for cosmology sed_names is 1d str array, with length = number of SED files in the library sed_mag_list is MxN float array, with M = number of SED files in the library, and N = number of top hat filters in the catalog sed_mag_norm is 1d float array, with length = number of SED files in the library cosmology = {'H0': H0, 'Om0': Om0} """ gc = GCRCatalogs.load_catalog(catalog_name, config_overwrite=dict(md5=False)) cosmo = dict(H0=gc.cosmology.H0.value, Om0=gc.cosmology.Om0) bp_params_raw = {'disk': set(), 'bulge': set()} for q in gc.list_all_quantities(): m = _gcr_sed_re.match(q) if m: wav0, width, tag = m.groups() bp_params_raw[tag].add((int(wav0), int(width))) assert bp_params_raw['disk'] == bp_params_raw[ 'bulge'], 'SEDs for disk and bulge do not match' assert bp_params_raw['disk'], 'No SED found' bp_params_sorted = sorted(bp_params_raw['disk'], key=lambda p: p[0]) # SED labels in GCR specify the band pass in angstrom, but CatSim uses nm # Hence the conversion factor 0.1 in the code below wav_min = bp_params_sorted[0][0] * 0.1 wav_max = max((0.1 * (wav0 + width) for wav0, width in bp_params_sorted)) wav_grid = np.arange(wav_min, wav_max, 0.1) bp_name_list = list() bp_list = list() for wav0, width in bp_params_sorted: sb_grid = ((wav_grid >= wav0 * 0.1) & (wav_grid <= (wav0 + width) * 0.1)).astype(float) bp_list.append(Bandpass(wavelen=wav_grid, sb=sb_grid)) bp_name_list.append('%d_%d' % (wav0, width)) bandpass_dict = BandpassDict(bp_list, bp_name_list) sed_names = list() sed_mag_list = list() sed_mag_norm = list() imsim_bp = Bandpass() imsim_bp.imsimBandpass() for sed_file_name in os.listdir(_galaxy_sed_dir): spec = Sed() spec.readSED_flambda(os.path.join(_galaxy_sed_dir, sed_file_name)) sed_names.append(sed_file_name) sed_mag_list.append(tuple(bandpass_dict.magListForSed(spec))) sed_mag_norm.append(spec.calcMag(imsim_bp)) return np.array(sed_names), np.array(sed_mag_list), np.array( sed_mag_norm), cosmo
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 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 get_phosimVars(self): """ Obtain variables sedFilepath to be used to obtain unique filenames for each SED for phoSim and MagNorm which is also used. Note that aside from acting as a getter, this also writes spectra to `self.sn_sedfile_prefix`snid_mjd_band.dat for each observation of interest """ # construct the unique filename # method: snid_mjd(to 4 places of decimal)_bandpassname mjd = "_{:0.4f}_".format(self.mjdobs) mjd += self.obs_metadata.bandpass + '.dat' fnames = np.array([self.sn_sedfile_prefix + str(int(elem)) + mjd if isinstance(elem, numbers.Number) else self.sn_sedfile_prefix + str(elem) + mjd for elem in self.column_by_name('snid')], dtype='str') c, x1, x0, t0, z = self.column_by_name('c'),\ self.column_by_name('x1'),\ self.column_by_name('x0'),\ self.column_by_name('t0'),\ self.column_by_name('redshift') bp = Bandpass() bp.imsimBandpass() magNorms = np.zeros(len(fnames)) snobject = SNObject() snobject.rectifySED = True for i in range(len(self.column_by_name('snid'))): # if t0 is nan, this was set by the catalog for dim SN, or SN # outside redshift range, We will not provide a SED file for these if np.isnan(t0[i]): magNorms[i] = np.nan fnames[i] = None else: snobject.set(c=c[i], x1=x1[i], x0=x0[i], t0=t0[i], z=z[i]) if snobject.modelOutSideTemporalRange == 'zero': if self.mjdobs > snobject.maxtime() or self.mjdobs < snobject.mintime(): magNorms[i] = np.nan fnames[i] = None # SED in rest frame sed = snobject.SNObjectSourceSED(time=self.mjdobs) try: magNorms[i] = sed.calcMag(bandpass=bp) except: # sed.flambda = 1.0e-20 magNorms[i] = 1000. # sed.calcMag(bandpass=bp) if self.writeSedFile: sed.writeSED(fnames[i]) return (fnames, magNorms)
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 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 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 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 _parallel_fitting(mag_array, redshift, redshift_true, H0, Om0, wav_min, wav_width, lsst_mag_array, out_dict, tag): pid = os.getpid() (sed_names, mag_norms, av_arr, rv_arr) = sed_from_galacticus_mags(mag_array, redshift, redshift_true, H0, Om0, wav_min, wav_width, lsst_mag_array) tot_bp_dict = BandpassDict.loadTotalBandpassesFromFiles() sed_dir = getPackageDir('sims_sed_library') lsst_fit_fluxes = np.zeros((6, len(sed_names)), dtype=float) t_start = time.time() ccm_w = None restframe_seds = {} imsim_bp = Bandpass() imsim_bp.imsimBandpass() n04_ln10 = -0.4 * np.log(10) for ii in range(len(sed_names)): av_val = av_arr[ii] rv_val = rv_arr[ii] sed_tag = '%s_%.3f_%.3f' % (sed_names[ii], av_val, rv_val) if sed_tag not in restframe_seds: rest_sed = Sed() rest_sed.readSED_flambda(os.path.join(sed_dir, sed_names[ii])) mag = rest_sed.calcMag(imsim_bp) if ccm_w is None or not np.array_equal(rest_sed.wavelen, ccm_w): ccm_w = np.copy(rest_sed.wavelen) ax, bx = rest_sed.setupCCM_ab() rest_sed.addDust(ax, bx, A_v=av_val, R_v=rv_val) restframe_seds[sed_tag] = (rest_sed, mag) for i_bp, bp in enumerate('ugrizy'): m_norm = mag_norms[i_bp][ii] if m_norm > 0.0 and not np.isfinite(m_norm): continue spec = Sed(wavelen=restframe_seds[sed_tag][0].wavelen, flambda=restframe_seds[sed_tag][0].flambda) fnorm = np.exp(n04_ln10 * (m_norm - restframe_seds[sed_tag][1])) try: assert np.isfinite(fnorm) assert fnorm > 0.0 except AssertionError: print('\n\nmagnorm %e\n\n' % (m_norm)) raise spec.multiplyFluxNorm(fnorm) spec.redshiftSED(redshift[ii], dimming=True) ff = spec.calcFlux(tot_bp_dict[bp]) lsst_fit_fluxes[i_bp][ii] = ff out_dict[tag] = (sed_names, mag_norms, av_arr, rv_arr, lsst_fit_fluxes)
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 Load_System(self): for f in self.filterlist: self.lsst_std[f] = Bandpass() #self.lsst_std[f].readThroughput(os.path.join(self.throughputsDir, 'total_'+f+'.dat')) self.lsst_system[f] = Bandpass() self.lsst_system[f].readThroughputList([ 'detector.dat', 'lens1.dat', 'lens2.dat', 'lens3.dat', 'm1.dat', 'm2.dat', 'm3.dat', 'filter_' + f + '.dat' ], rootDir=self.throughputsDir)
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 calcADUwrapper(sedName=None, magNorm=None, redshift=None, internalAv=None, internalRv=None, galacticAv=None, galacticRv=None, bandpass=None): """ Read in an SED and calculat the number of ADU produced by that SED in a specified bandpass Parameters ---------- sedName is a string specifying the file name of the SED magNorm is the normalizing magnitude of the SED in the imsimBandpass redshift is the redshift of the SED internalAv is the Av due to internal dust of the source (if a galaxy) internalRv is the Rv due to internal dust of the source (if a galaxy) galacticAv is the Av due to Milky Way dust between observer and source galacticRv is the Rv due to Milky Way dust between observer and source bandpass is an intantiation of Bandpass representing the band in which the ADUs are measured Returns ------- A float representing the number of ADUs measured in the bandpass """ imsimband = Bandpass() imsimband.imsimBandpass() sed = Sed() sed.readSED_flambda(sedName) fNorm = sed.calcFluxNorm(magNorm, imsimband) sed.multiplyFluxNorm(fNorm) if internalAv is not None and internalRv is not None: if internalAv != 0.0 and internalRv != 0.0: a_int, b_int = sed.setupCCM_ab() sed.addDust(a_int, b_int, A_v=internalAv, R_v=internalRv) if redshift is not None and redshift != 0.0: sed.redshiftSED(redshift, dimming=True) a_int, b_int = sed.setupCCM_ab() sed.addDust(a_int, b_int, A_v=galacticAv, R_v=galacticRv) adu = sed.calcADU(bandpass, photParams=PhotometricParameters()) return adu
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 setUpClass(cls): cls.scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='allowedChipsTest-') cls.obs = ObservationMetaData(pointingRA=122.0, pointingDec=-29.1, mjd=57381.2, rotSkyPos=43.2, bandpassName='r') cls.camera = camTestUtils.CameraWrapper().camera cls.dbFileName = os.path.join(cls.scratchDir, 'allowed_chips_test_db.txt') if os.path.exists(cls.dbFileName): os.unlink(cls.dbFileName) cls.controlSed = Sed() cls.controlSed.readSED_flambda(os.path.join(getPackageDir('sims_sed_library'), 'flatSED', 'sed_flat.txt.gz')) cls.magNorm = 18.1 imsim = Bandpass() imsim.imsimBandpass() ff = cls.controlSed.calcFluxNorm(cls.magNorm, imsim) cls.controlSed.multiplyFluxNorm(ff) a_x, b_x = cls.controlSed.setupCCMab() cls.controlSed.addCCMDust(a_x, b_x, A_v=0.1, R_v=3.1) bpd = BandpassDict.loadTotalBandpassesFromFiles() pp = PhotometricParameters() cls.controlADU = cls.controlSed.calcADU(bpd['u'], pp) cls.countSigma = np.sqrt(cls.controlADU/pp.gain) cls.x_pix = 50 cls.y_pix = 50 x_list = [] y_list = [] name_list = [] for dd in cls.camera: x_list.append(cls.x_pix) y_list.append(cls.y_pix) name_list.append(dd.getName()) x_list = np.array(x_list) y_list = np.array(y_list) ra_list, dec_list = raDecFromPixelCoords(x_list, y_list, name_list, camera=cls.camera, obs_metadata=cls.obs, epoch=2000.0) dra_list = 3600.0*(ra_list-cls.obs.pointingRA) ddec_list = 3600.0*(dec_list-cls.obs.pointingDec) create_text_catalog(cls.obs, cls.dbFileName, dra_list, ddec_list, mag_norm=[cls.magNorm]*len(dra_list)) cls.db = allowedChipsFileDBObj(cls.dbFileName, runtable='test')
def setUpClass(cls): cls.scratchDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'scratchSpace') cls.obs = ObservationMetaData(pointingRA=122.0, pointingDec=-29.1, mjd=57381.2, rotSkyPos=43.2) cls.camera = camTestUtils.CameraWrapper().camera cls.dbFileName = os.path.join(cls.scratchDir, 'allowed_chips_test_db.txt') if os.path.exists(cls.dbFileName): os.unlink(cls.dbFileName) cls.controlSed = Sed() cls.controlSed.readSED_flambda(os.path.join(getPackageDir('sims_sed_library'), 'flatSED','sed_flat.txt.gz')) cls.magNorm = 18.1 imsim = Bandpass() imsim.imsimBandpass() ff = cls.controlSed.calcFluxNorm(cls.magNorm, imsim) cls.controlSed.multiplyFluxNorm(ff) a_x, b_x = cls.controlSed.setupCCMab() cls.controlSed.addCCMDust(a_x, b_x, A_v=0.1, R_v=3.1) bpd = BandpassDict.loadTotalBandpassesFromFiles() pp = PhotometricParameters() cls.controlADU = cls.controlSed.calcADU(bpd['u'], pp) cls.countSigma = np.sqrt(cls.controlADU/pp.gain) cls.x_pix = 50 cls.y_pix = 50 x_list = [] y_list = [] name_list = [] for dd in cls.camera: x_list.append(cls.x_pix) y_list.append(cls.y_pix) name_list.append(dd.getName()) x_list = np.array(x_list) y_list = np.array(y_list) ra_list, dec_list = raDecFromPixelCoords(x_list, y_list, name_list, camera=cls.camera, obs_metadata=cls.obs, epoch=2000.0) dra_list = 3600.0*(ra_list-cls.obs.pointingRA) ddec_list = 3600.0*(dec_list-cls.obs.pointingDec) create_text_catalog(cls.obs, cls.dbFileName, dra_list, ddec_list, mag_norm=[cls.magNorm]*len(dra_list)) cls.db = allowedChipsFileDBObj(cls.dbFileName, runtable='test')
def calcMagNorm(self, objectMags, sedObj, bandpassDict, mag_error = None, redshift = None, filtRange = None): """ This will find the magNorm value that gives the closest match to the magnitudes of the object using the matched SED. Uses scipy.optimize.leastsq to find the values of fluxNorm that minimizes the function: ((flux_obs - (fluxNorm*flux_model))/flux_error)**2. @param [in] objectMags are the magnitude values for the object with extinction matching that of the SED object. In the normal case using the selectSED routines above it will be dereddened mags. @param [in] sedObj is an Sed class instance that is set with the wavelength and flux of the matched SED @param [in] bandpassDict is a BandpassDict class instance with the Bandpasses set to those for the magnitudes given for the catalog object @param [in] mag_error are provided error values for magnitudes in objectMags. If none provided then this defaults to 1.0. This should be an array of the same length as objectMags. @param [in] redshift is the redshift of the object if the magnitude is observed @param [in] filtRange is a selected range of filters specified by their indices in the bandpassList to match up against. Used when missing data in some magnitude bands. @param [out] bestMagNorm is the magnitude normalization for the given magnitudes and SED """ import scipy.optimize as opt sedTest = Sed() sedTest.setSED(sedObj.wavelen, flambda = sedObj.flambda) if redshift is not None: sedTest.redshiftSED(redshift) imSimBand = Bandpass() imSimBand.imsimBandpass() zp = -2.5*np.log10(3631) #Note using default AB zeropoint flux_obs = np.power(10,(objectMags + zp)/(-2.5)) sedTest.resampleSED(wavelen_match=bandpassDict.wavelenMatch) sedTest.flambdaTofnu() flux_model = sedTest.manyFluxCalc(bandpassDict.phiArray, bandpassDict.wavelenStep) if filtRange is not None: flux_obs = flux_obs[filtRange] flux_model = flux_model[filtRange] if mag_error is None: flux_error = np.ones(len(flux_obs)) else: flux_error = np.abs(flux_obs*(np.log(10)/(-2.5))*mag_error) bestFluxNorm = opt.leastsq(lambda x: ((flux_obs - (x*flux_model))/flux_error), 1.0)[0][0] sedTest.multiplyFluxNorm(bestFluxNorm) bestMagNorm = sedTest.calcMag(imSimBand) return bestMagNorm
def lsst_filters(): throughPath = os.path.join(getPackageDir('throughputs'), 'baseline') lsstKeys = ['u', 'g', 'r', 'i', 'z', 'y'] bps = {} for key in lsstKeys: bp = np.loadtxt(os.path.join(throughPath, 'total_'+key+'.dat'), dtype=zip(['wave', 'trans'], [float]*2)) bpTemp = Bandpass() good = np.where(bp['trans'] > 0.) bpTemp.setBandpass(bp['wave'], bp['trans'], wavelen_min=bp['wave'][good].min(), wavelen_max=bp['wave'][good].max()) bps[key] = bpTemp return bps
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 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 Load_System(self): for f in self.filterlist: self.lsst_std[f] = Bandpass() #self.lsst_std[f].readThroughput(os.path.join(self.throughputsDir, 'total_'+f+'.dat')) self.lsst_system[f] = Bandpass() index = [ i for i, x in enumerate(self.filter_files) if f + '.dat' in x ] self.lsst_system[f].readThroughputList( self.telescope_files + [self.filter_files[index[0]]], rootDir=self.throughputsDir, wavelen_min=self.wave_min, wavelen_max=self.wave_max)
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 _create_sed_library_mags(wav_min, wav_width): """ Calculate the magnitudes of the SEDs in sims_sed_library dir in the tophat filters specified by wav_min, wav_width Parameters ---------- wav_min is a numpy array of the minimum wavelengths of the tophat filters (in nm) wav_width is a numpy array of the widths of the tophat filters (in nm) Returns ------- sed_names is an array containing the names of the SED files sed_mag_list is MxN float array, with M = number of SED files in the library, and N = number of top hat filters in the catalog sed_mag_norm is 1d float array, with length = number of SED files in the library """ wav_max = max((wav0 + width for wav0, width in zip(wav_min, wav_width))) wav_grid = np.arange(wav_min.min(), wav_max, 0.1) bp_name_list = list() bp_list = list() for wav0, width in zip(wav_min, wav_width): sb_grid = ((wav_grid >= wav0) & (wav_grid <= (wav0 + width))).astype(float) bp_list.append(Bandpass(wavelen=wav_grid, sb=sb_grid)) bp_name_list.append('%d_%d' % (wav0, width)) bandpass_dict = BandpassDict(bp_list, bp_name_list) sed_names = list() sed_mag_list = list() sed_mag_norm = list() imsim_bp = Bandpass() imsim_bp.imsimBandpass() for sed_file_name in os.listdir(_galaxy_sed_dir): spec = Sed() spec.readSED_flambda(os.path.join(_galaxy_sed_dir, sed_file_name)) sed_names.append(defaultSpecMap[sed_file_name]) sed_mag_list.append(tuple(bandpass_dict.magListForSed(spec))) sed_mag_norm.append(spec.calcMag(imsim_bp)) return np.array(sed_names), np.array(sed_mag_list), np.array(sed_mag_norm)
def addAerosol(atmosphere, X, tau0=0.05, alpha=1.0, wavelen0=440.0, plotAtmosphere=True): # Calculate the aerosol contribution -- sb with aerosols = sb*exp(-tau) tau = tau0 * np.power((wavelen0/atmosphere.wavelen), alpha) # Generate new atmosphere bandpass with aerosols. atmosphere_aerosol = Bandpass() atmosphere_aerosol.setBandpass(wavelen = atmosphere.wavelen, sb = atmosphere.sb * np.exp(-tau*X)) if plotAtmosphere: # Plot for a check: atmodict = {'Original atmosphere':atmosphere, 'With aerosols': atmosphere_aerosol} bu.plotBandpasses(atmodict) return atmosphere_aerosol
def read_filtersonly(shift_perc=None): # read the filter throughput curves only (called from read_hardware as well) # apply a shift of +shift_perc/100 * eff_wavelength to the wavelengths of the filter. filterdir = os.getenv("LSST_THROUGHPUTS_DEFAULT") filters = {} for f in filterlist: filters[f] = Bandpass() filters[f].readThroughput(os.path.join(filterdir, "filter_" + f + ".dat")) effwavelenphi, effwavelensb = filters[f].calcEffWavelen() if shift_perc != None: shift = effwavelensb * shift_perc/100.0 print f, shift filters[f].wavelen = filters[f].wavelen + shift filters[f].resampleBandpass() return filters
def _calcSingleGalSimSed(self, sedName, zz, iAv, iRv, gAv, gRv, norm): """ correct the SED for redshift, dust, etc. Return an Sed object as defined in sims_photUtils/../../Sed.py """ if is_null(sedName): return None sed = self._getSedCopy(sedName) imsimband = Bandpass() imsimband.imsimBandpass() #normalize the SED #Consulting the file sed.py in GalSim/galsim/ it appears that GalSim expects #its SEDs to ultimately be in units of ergs/nm so that, when called, they can #be converted to photons/nm (see the function __call__() and the assignment of #self._rest_photons in the __init__() of galsim's sed.py file). Thus, we need #to read in our SEDs, normalize them, and then multiply by the exposure time #and the effective area to get from ergs/s/cm^2/nm to ergs/nm. # #The gain parameter should convert between photons and ADU (so: it is the #traditional definition of "gain" -- electrons per ADU -- multiplied by the #quantum efficiency of the detector). Because we fold the quantum efficiency #of the detector into our total_[u,g,r,i,z,y].dat bandpass files #(see the readme in the THROUGHPUTS_DIR/baseline/), we only need to multiply #by the electrons per ADU gain. # #We will take these parameters from an instantiation of the PhotometricParameters #class (which can be reassigned by defining a daughter class of this class) # fNorm = sed.calcFluxNorm(norm, imsimband) sed.multiplyFluxNorm(fNorm) # apply dust extinction (internal) if iAv != 0.0 and iRv != 0.0: a_int, b_int = sed.setupCCMab() sed.addCCMDust(a_int, b_int, A_v=iAv, R_v=iRv) # 22 June 2015 # apply redshift; there is no need to apply the distance modulus from # sims/photUtils/CosmologyWrapper; magNorm takes that into account # however, magNorm does not take into account cosmological dimming if zz != 0.0: sed.redshiftSED(zz, dimming=True) # apply dust extinction (galactic) if gAv != 0.0 and gRv != 0.0: a_int, b_int = sed.setupCCMab() sed.addCCMDust(a_int, b_int, A_v=gAv, R_v=gRv) return sed
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 make_response_func(magnorm=16., filename='starSED/wDs/bergeron_14000_85.dat_14200.gz', savefile='gaia_response.npz', noise=1, count_min=8., bluecut=700., redcut=650): """ Declare some stars as "standards" and build a simple GAIA response function? Multiply GAIA observations by response function to get spectra in flambda units. """ imsimBand = Bandpass() imsimBand.imsimBandpass() sed_dir = getPackageDir('sims_sed_library') filepath = os.path.join(sed_dir, filename) wd = Sed() wd.readSED_flambda(filepath) # Let's just use a flat spectrum wd.setFlatSED() fNorm = wd.calcFluxNorm(magnorm, imsimBand) wd.multiplyFluxNorm(fNorm) red_wd = copy.copy(wd) blue_wd = copy.copy(wd) gaia_obs = SED2GAIA(wd, noise=noise) red_wd.resampleSED(wavelen_match = gaia_obs['RP_wave']) blue_wd.resampleSED(wavelen_match = gaia_obs['BP_wave']) if noise == 1: red_response = red_wd.flambda / gaia_obs['noisySpec'][0]['RPNoisySpec'] blue_response = blue_wd.flambda / gaia_obs['noisySpec'][0]['BPNoisySpec'] too_low = np.where(gaia_obs['noisySpec'][0]['RPNoisySpec'] < count_min) red_response[too_low] = 0 too_low = np.where(gaia_obs['noisySpec'][0]['BPNoisySpec'] < count_min) blue_response[too_low] = 0 elif noise == 0: red_response = red_wd.flambda / gaia_obs['noiseFreeSpec']['RPNoiseFreeSpec'] blue_response = blue_wd.flambda / gaia_obs['noiseFreeSpec']['BPNoiseFreeSpec'] too_low = np.where(gaia_obs['noiseFreeSpec']['RPNoiseFreeSpec'] < count_min) red_response[too_low] = 0 too_low = np.where(gaia_obs['noiseFreeSpec']['BPNoiseFreeSpec'] < count_min) blue_response[too_low] = 0 blue_response[np.where(gaia_obs['BP_wave'] > bluecut)] = 0. red_response[np.where(gaia_obs['RP_wave'] < redcut)] = 0. # XXX check the mags of the original WD and the blue and red WD. np.savez(savefile, red_response=red_response, blue_response=blue_response, red_wavelen=gaia_obs['RP_wave'], blue_wavelen=gaia_obs['BP_wave'])
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 stubb_fitlers(wave_min=350., wave_max=1050): """ Define some narrow filters that overlap LSST u and y, and are in GAIA overlap. """ throughPath = os.path.join(getPackageDir('throughputs'), 'baseline') bps = {} lsstKeys = ['u', 'y'] bps = {} for key in lsstKeys: bp = np.loadtxt(os.path.join(throughPath, 'total_'+key+'.dat'), dtype=zip(['wave', 'trans'], [float]*2)) bpTemp = Bandpass() good = np.where((bp['trans'] > 0.) & (bp['wave'] > wave_min) & (bp['wave'] < wave_max)) bpTemp.setBandpass(bp['wave'], bp['trans'], wavelen_min=bp['wave'][good].min(), wavelen_max=bp['wave'][good].max()) bps[key+'_truncated'] = bpTemp return bps
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 read_hardware(shift_perc=None): # read system (hardware) transmission, return dictionary of system hardware (keyed to filter) filterdir = os.getenv("LSST_THROUGHPUTS_DEFAULT") hardware = ("detector.dat", "m1.dat", "m2.dat", "m3.dat", "lens1.dat", "lens2.dat", "lens3.dat") # Read in the standard components, but potentially shift the filter by shift_perc percent. filters = read_filtersonly(shift_perc=shift_perc) sys = {} for f in filterlist: sys[f] = Bandpass() # put together the standard component list tlist = [] for t in hardware: tlist.append(os.path.join(filterdir, t)) # read in the standard components, combine into sys sys[f].readThroughputList(tlist) # multiply by the filter throughput for final hardware throughput (no atmosphere) sys[f].wavelen, sys[f].sb = sys[f].multiplyThroughputs(filters[f].wavelen, filters[f].sb) return sys