def Calc_m5(self, filtre): filtre_trans = self.system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) flatSedb = Sed() flatSedb.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0b = np.power(10., -0.4 * self.mag_sky[filtre]) flatSedb.multiplyFluxNorm(flux0b) photParams = PhotometricParameters(bandpass=filtre) norm = photParams.platescale**2 / 2. * photParams.exptime / photParams.gain if self.atmos: self.data['m5'][filtre] = SignalToNoise.calcM5( flatSedb, self.atmosphere[filtre], self.system[filtre], photParams=photParams, FWHMeff=self.FWHMeff[filtre]) adu_int = flatSedb.calcADU(bandpass=self.atmosphere[filtre], photParams=photParams) self.data['flux_sky'][filtre] = adu_int * norm else: self.data['m5'][filtre] = SignalToNoise.calcM5( flatSedb, self.system[filtre], self.system[filtre], photParams=photParams, FWHMeff=self.FWHMeff[filtre]) adu_int = flatSedb.calcADU(bandpass=self.system[filtre], photParams=photParams) self.data['flux_sky'][filtre] = adu_int * norm
def ZP_filtre(self, filtre): self.data['Skyb'][filtre] = self.Cte * np.power( self.Diameter / 6.5, 2.) * np.power(self.DeltaT / 30., 2.) * np.power( self.platescale, 2.) * np.power( 10., 0.4 * (25. - self.mag_sky[filtre])) * self.Sigmab[filtre] Zb = 181.8 * np.power(self.Diameter / 6.5, 2.) * self.Tb[filtre] mbZ = 25. + 2.5 * np.log10(Zb) filtre_trans = self.throughputs.system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) flatSed = Sed() flatSed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0 = np.power(10., -0.4 * mbZ) flatSed.multiplyFluxNorm(flux0) counts = flatSed.calcADU( bandpass, photParams=self.photParams) #number of counts for exptime self.data['zp'][filtre] = mbZ #print 'hello',counts/self.photParams.exptime self.data['counts_zp'][filtre] = counts / self.photParams.exptime
def __call__(self, filter_name='u', magNorm=None): """ This method calls the SkyCountsPerSec object and calculates the sky counts. @param [in] filter_name is a string that indicates the name of the filter for which to make the calculation. @param [in] magNorm is an option to calculate the sky counts for a given magnitude. When calculating the counts from just the information in skyModel this should be set as MagNorm=None. """ bandpass = self.bandpassdic[filter_name] wave, spec = self.skyModel.returnWaveSpec() skymodel_Sed = Sed(wavelen=wave, flambda=spec[0, :]) if magNorm: skymodel_fluxNorm = skymodel_Sed.calcFluxNorm(magNorm, bandpass) skymodel_Sed.multiplyFluxNorm(skymodel_fluxNorm) sky_counts = skymodel_Sed.calcADU(bandpass=bandpass, photParams=self.photParams) expTime = self.photParams.nexp * self.photParams.exptime * u.s sky_counts_persec = sky_counts * 0.2**2 / expTime return sky_counts_persec
def get_sed(name, magnorm, redshift, av, rv): if not hasattr(get_sed, '_rest_dict'): get_sed._rest_dict = {} get_sed._imsim_bp = Bandpass() get_sed._imsim_bp.imsimBandpass() get_sed._sed_dir = os.environ['SIMS_SED_LIBRARY_DIR'] get_sed._ccm_w = None tag = '%s_%.2f_%.2f' % (name, av, rv) if tag not in get_sed._rest_dict: ss = Sed() ss.readSED_flambda(os.path.join(get_sed._sed_dir, name)) if get_sed._ccm_w is None or not np.array_equal( ss.wavelen, get_sed._ccm_w): get_sed._ccm_w = np.copy(ss.wavelen) get_sed._ax, get_sed._bx = ss.setupCCM_ab() mn = ss.calcMag(get_sed._imsim_bp) ss.addDust(get_sed._ax, get_sed._bx, A_v=av, R_v=rv) get_sed._rest_dict[tag] = (ss, mn) base_sed = get_sed._rest_dict[tag][0] ss = Sed(wavelen=base_sed.wavelen, flambda=base_sed.flambda) dmag = magnorm - get_sed._rest_dict[tag][1] fnorm = np.power(10.0, -0.4 * dmag) ss.multiplyFluxNorm(fnorm) ss.redshiftSED(redshift, dimming=True) return ss
def _fluxes(sed_name, mag_norm, redshift): """ Find the fluxes for a galaxy component Parameters ---------- sed_name is an SED file name mag_norm is a float redshift is a float Returns ------- array of fluxes in ugrizy order """ if not hasattr(_fluxes, '_bp_dict'): bp_dir = getPackageDir('throughputs') bp_dir = os.path.join(bp_dir, 'imsim', 'goal') _fluxes._bp_dict = BandpassDict.loadTotalBandpassesFromFiles( bandpassDir=bp_dir) _fluxes._sed_dir = getPackageDir('sims_sed_library') spec = Sed() full_sed_name = os.path.join(_fluxes._sed_dir, sed_name) if not os.path.isfile(full_sed_name): full_sed_name = os.path.join(_fluxes._sed_dir, defaultSpecMap[sed_name]) spec.readSED_flambda(full_sed_name) fnorm = getImsimFluxNorm(spec, mag_norm) spec.multiplyFluxNorm(fnorm) spec.redshiftSED(redshift, dimming=True) return _fluxes._bp_dict.fluxListForSed(spec)
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 sky_counts_per_sec(skyModel, photParams, bandpass, magNorm=None): """ Compute the sky background counts per pixel per second. Note that the gain in photParams is applied to the return value such that "counts" are in units of ADU. Parameters ---------- skyModel: lsst.sims.skybrightness.SkyModel Model of the sky for the current epoch. photParams: lsst.sims.photUtils.PhotometricParameters Object containing parameters of the photometric response of the telescope, including pixel scale, gain, effective area, exposure time, number of exposures, etc. bandpass: lsst.sims.photUtils.Bandpass Instrumental throughput for a particular passband. magNorm: float [None] If not None, then renormalize the sky SED to have a monochromatic magnitude of magNorm at 500nm. Otherwise, use the default skyModel normalization. Returns ------- ADUs per second per pixel """ wave, spec = skyModel.returnWaveSpec() sed = Sed(wavelen=wave, flambda=spec[0, :]) if magNorm is not None: flux_norm = sed.calcFluxNorm(magNorm, bandpass) sed.multiplyFluxNorm(flux_norm) countrate_per_arcsec = sed.calcADU(bandpass=bandpass, photParams=photParams) exptime = photParams.nexp * photParams.exptime return countrate_per_arcsec * photParams.platescale**2 / exptime
def calculate_mags(sed_name, mag_norm, out_dict): """ Parameters ---------- sed_name is a numpy array of SED names mag_norm is a numpy array of magNorms out_dict is a multiprocessing.Manager.dict() that will store the magnitudes calculated by this process. """ i_process = mp.current_process().pid bp_dir = getPackageDir('throughputs') bp_dir = os.path.join(bp_dir, 'imsim', 'goal') bp_dict = BandpassDict.loadTotalBandpassesFromFiles(bandpassDir=bp_dir) sed_dir = getPackageDir('sims_sed_library') out_mags = np.zeros((len(sed_name), 6), dtype=float) for i_star, (s_name, m_norm) in enumerate(zip(sed_name, mag_norm)): spec = Sed() spec.readSED_flambda(os.path.join(sed_dir, defaultSpecMap[s_name])) fnorm = getImsimFluxNorm(spec, m_norm) spec.multiplyFluxNorm(fnorm) mags = bp_dict.magListForSed(spec) out_mags[i_star] = mags out_dict[i_process] = out_mags
def ZP_filtre(self, filtre): photParams = PhotometricParameters(bandpass=filtre) Diameter = 2. * np.sqrt( photParams.effarea * 1.e-4 / np.pi) # diameter in meter Cte = 3631. * np.pi * Diameter**2 * 2. * photParams.exptime / 4 / h / 1.e36 #print('hello Cte',Cte,Diameter,h,photParams.exptime) self.data['Skyb'][filtre] = Cte * np.power( Diameter / 6.5, 2.) * np.power( 2. * photParams.exptime / 30., 2.) * np.power( photParams.platescale, 2.) * np.power( 10., 0.4 * (25. - self.mag_sky[filtre])) * self.Sigmab[filtre] Zb = 181.8 * np.power(Diameter / 6.5, 2.) * self.Tb[filtre] mbZ = 25. + 2.5 * np.log10(Zb) filtre_trans = self.system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) flatSed = Sed() flatSed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0 = np.power(10., -0.4 * mbZ) flatSed.multiplyFluxNorm(flux0) photParams = PhotometricParameters(bandpass=filtre) counts = flatSed.calcADU( bandpass, photParams=photParams) #number of counts for exptime self.data['zp'][filtre] = mbZ #print 'hello',counts/self.photParams.exptime self.data['counts_zp'][filtre] = counts / 2. * photParams.exptime
def setM5(m5target, skysed, totalBandpass, hardware, photParams, FWHMeff=None): """ Take an SED representing the sky and normalize it so that m5 (the magnitude at which an object is detected in this bandpass at 5-sigma) is set to some specified value. The 5-sigma limiting magnitude (m5) for an observation is determined by a combination of the telescope and camera parameters (such as diameter of the mirrors and the readnoise) together with the sky background. This method (setM5) scales a provided sky background Sed so that an observation would have a target m5 value, for the provided hardware parameters. Using the resulting Sed in the 'calcM5' method will return this target value for m5. @param [in] the desired value of m5 @param [in] skysed is an instantiation of the Sed class representing sky emission @param [in] totalBandpass is an instantiation of the Bandpass class representing the total throughput of the telescope (instrumentation plus atmosphere) @param [in] hardware is an instantiation of the Bandpass class representing the throughput due solely to instrumentation. @param [in] photParams is an instantiation of the PhotometricParameters class that carries details about the photometric response of the telescope. @param [in] FWHMeff in arcseconds @param [out] returns an instantiation of the Sed class that is the skysed renormalized so that m5 has the desired value. Note that the returned SED will be renormalized such that calling the method self.calcADU(hardwareBandpass) on it will yield the number of counts per square arcsecond in a given bandpass. """ #This is based on the LSST SNR document (v1.2, May 2010) #www.astro.washington.edu/users/ivezic/Astr511/LSST_SNRdoc.pdf if FWHMeff is None: FWHMeff = LSSTdefaults().FWHMeff('r') skyCountsTarget = calcSkyCountsPerPixelForM5(m5target, totalBandpass, FWHMeff=FWHMeff, photParams=photParams) skySedOut = Sed(wavelen=numpy.copy(skysed.wavelen), flambda=numpy.copy(skysed.flambda)) skyCounts = skySedOut.calcADU(hardware, photParams=photParams) \ * photParams.platescale * photParams.platescale skySedOut.multiplyFluxNorm(skyCountsTarget / skyCounts) return skySedOut
def setM5(m5target, skysed, totalBandpass, hardware, photParams, FWHMeff = None): """ Take an SED representing the sky and normalize it so that m5 (the magnitude at which an object is detected in this bandpass at 5-sigma) is set to some specified value. The 5-sigma limiting magnitude (m5) for an observation is determined by a combination of the telescope and camera parameters (such as diameter of the mirrors and the readnoise) together with the sky background. This method (setM5) scales a provided sky background Sed so that an observation would have a target m5 value, for the provided hardware parameters. Using the resulting Sed in the 'calcM5' method will return this target value for m5. @param [in] the desired value of m5 @param [in] skysed is an instantiation of the Sed class representing sky emission @param [in] totalBandpass is an instantiation of the Bandpass class representing the total throughput of the telescope (instrumentation plus atmosphere) @param [in] hardware is an instantiation of the Bandpass class representing the throughput due solely to instrumentation. @param [in] photParams is an instantiation of the PhotometricParameters class that carries details about the photometric response of the telescope. @param [in] FWHMeff in arcseconds @param [out] returns an instantiation of the Sed class that is the skysed renormalized so that m5 has the desired value. Note that the returned SED will be renormalized such that calling the method self.calcADU(hardwareBandpass) on it will yield the number of counts per square arcsecond in a given bandpass. """ #This is based on the LSST SNR document (v1.2, May 2010) #www.astro.washington.edu/users/ivezic/Astr511/LSST_SNRdoc.pdf if FWHMeff is None: FWHMeff = LSSTdefaults().FWHMeff('r') skyCountsTarget = calcSkyCountsPerPixelForM5(m5target, totalBandpass, FWHMeff=FWHMeff, photParams=photParams) skySedOut = Sed(wavelen=numpy.copy(skysed.wavelen), flambda=numpy.copy(skysed.flambda)) skyCounts = skySedOut.calcADU(hardware, photParams=photParams) \ * photParams.platescale * photParams.platescale skySedOut.multiplyFluxNorm(skyCountsTarget/skyCounts) return skySedOut
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 testSignalToNoise(self): """ Test that calcSNR_m5 and calcSNR_sed give similar results """ defaults = LSSTdefaults() photParams = PhotometricParameters() m5 = [] for i in range(len(self.hardwareList)): m5.append( snr.calcM5( self.skySed, self.bpList[i], self.hardwareList[i], photParams, seeing=defaults.seeing(self.filterNameList[i]), ) ) sedDir = lsst.utils.getPackageDir("sims_sed_library") sedDir = os.path.join(sedDir, "starSED", "kurucz") fileNameList = os.listdir(sedDir) numpy.random.seed(42) offset = numpy.random.random_sample(len(fileNameList)) * 2.0 for ix, name in enumerate(fileNameList): if ix > 100: break spectrum = Sed() spectrum.readSED_flambda(os.path.join(sedDir, name)) ff = spectrum.calcFluxNorm(m5[2] - offset[ix], self.bpList[2]) spectrum.multiplyFluxNorm(ff) magList = [] controlList = [] magList = [] for i in range(len(self.bpList)): controlList.append( snr.calcSNR_sed( spectrum, self.bpList[i], self.skySed, self.hardwareList[i], photParams, defaults.seeing(self.filterNameList[i]), ) ) magList.append(spectrum.calcMag(self.bpList[i])) testList, gammaList = snr.calcSNR_m5( numpy.array(magList), numpy.array(self.bpList), numpy.array(m5), photParams ) for tt, cc in zip(controlList, testList): msg = "%e != %e " % (tt, cc) self.assertTrue(numpy.abs(tt / cc - 1.0) < 0.001, 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 quasarMag(z, M1450, survey, f): if (z, M1450, survey, f) in magCache: return magCache[(z, M1450, survey, f)] # for files containing $\lambda$ / F$_\lambda$, we use the Sed method # readSED_flambda. For files containing $\lambda$ / F$_\nu$, # we would use the readSED_fnu method instead. # get the path to the SED file for this z sedFilename = config.sedFilenameFormat.format(config.reddening, z) spectrumFilename = os.path.join(config.sedDir, sedFilename) # Read the spectrum. agn = Sed() agn.readSED_flambda(spectrumFilename) # Suppose you had a spectrum, but it didn't have an absolute scale. Or you # wanted to scale it to have a given magnitude in a particular bandpass. # For example, say we wanted to make our 'agn' spectrum have an r band # magnitude of 20, then calculate the magnitudes in all bandpasses. We # just use the calcFluxNorm and multiplyFluxNorm methods. # Scale spectrum and recalculate magnitudes. # given an absolute M1450, the observed magnitude m corresponding # to rest-frame 145nm radiation is # m = M1450+5log(d_L/10pc) - 2.5log(1+z) # so let's calculate m and then normalize our spectrum to that # first we need d_L = (1+z) * comoving distance # comoving distance is D_hubble * int_0^z dz'/sqrt(omegaM(1+z)^3+omegaLambda) def E(zp): return np.sqrt(config.omegaM * (1 + zp)**3 + config.omegaLambda) DC = config.DH * integrate.quad(lambda zp: 1 / E(zp), 0, z)[0] DL = (1 + z) * DC DL = DL * config.m2pc m = M1450 + 5 * np.log10(DL / 10) - 2.5 * np.log10(1 + z) # make a square bandpass at 145nm (in the quasar rest frame) # with a width of 1nm wavelen = np.arange(300, 2000, 0.1) sb = np.zeros(wavelen.shape) id1450 = int(((145 * (1 + z)) - 300) / 0.1) sb[id1450 - 5:id1450 + 5] = 1 band1450 = Bandpass(wavelen=wavelen, sb=sb) # normalize the sed to m at the (rest-frame) 1450A bandpass fluxNorm = agn.calcFluxNorm(m, band1450) agn.multiplyFluxNorm(fluxNorm) # Calculate expected AB magnitudes in the requested lsst band bandpass = f2Throughput(survey, f) mag = agn.calcMag(bandpass) magCache[(z, M1450, survey, f)] = mag return mag
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 Get_m5(self,filtre,mag_SN,msky,photParams,FWHMeff): wavelen_min, wavelen_max, wavelen_step=self.transmission.lsst_system[filtre].getWavelenLimits(None,None,None) flatSed = Sed() flatSed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0=np.power(10.,-0.4*msky) flatSed.multiplyFluxNorm(flux0) m5_calc=SignalToNoise.calcM5(flatSed,self.transmission.lsst_atmos_aerosol[filtre],self.transmission.lsst_system[filtre],photParams=photParams,FWHMeff=FWHMeff) snr_m5_through,gamma_through=SignalToNoise.calcSNR_m5(mag_SN,self.transmission.lsst_atmos_aerosol[filtre],m5_calc,photParams) return m5_calc,snr_m5_through
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 testVerboseSNR(self): """ Make sure that calcSNR_sed has everything it needs to run in verbose mode """ photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) snr.calcSNR_sed(spectrum, self.bpList[0], self.skySed, self.hardwareList[0], photParams, FWHMeff=0.7, verbose=True)
def Calc_Sky(self, paper, infos, transmission): Diameter = 6.5 #m Deltat = 30 #s platescale = 0.2 #arsec gain = 2.3 for filtre in self.filters: filtre_trans = transmission.lsst_system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) photParams = PhotometricParameters() #photParams._exptime=30. bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) infos['Skyb'][filtre] = 5455 * np.power( Diameter / 6.5, 2.) * np.power(Deltat / 30., 2.) * np.power( platescale, 2.) * np.power( 10., 0.4 * (25. - infos['mbsky'][filtre])) * infos['Sigmab'][filtre] Zb = 181.8 * np.power(Diameter / 6.5, 2.) * infos['Tb'][filtre] mbZ = 25. + 2.5 * np.log10(Zb) flatSed = Sed() flatSed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0 = np.power(10., -0.4 * mbZ) flatSed.multiplyFluxNorm(flux0) counts = flatSed.calcADU( bandpass, photParams=photParams) #number of counts for exptime infos['mb_Z'][filtre] = mbZ infos['counts_mb_Z'][filtre] = counts / photParams.exptime flatSedb = Sed() flatSedb.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0b = np.power(10., -0.4 * infos['mbsky'][filtre]) flatSedb.multiplyFluxNorm(flux0b) FWHMeff = SignalToNoise.FWHMgeom2FWHMeff(paper['Seeing'][filtre]) #FWHMeff = paper['Seeing'][filtre] #m5_calc=SignalToNoise.calcM5(flatSedb,transmission.lsst_atmos[filtre],transmission.lsst_system[filtre],photParams=photParams,FWHMeff=FWHMeff) m5_calc = SignalToNoise.calcM5( flatSedb, transmission.lsst_atmos[filtre], transmission.lsst_system[filtre], photParams=photParams, FWHMeff=self.paper['FWHMeff'][filtre]) infos['fiveSigmaDepth'][filtre] = m5_calc
def testVerboseSNR(self): """ Make sure that calcSNR_sed has everything it needs to run in verbose mode """ defaults = LSSTdefaults() photParams = PhotometricParameters() #create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) snr.calcSNR_sed(spectrum, self.bpList[0], self.skySed, self.hardwareList[0], photParams, seeing=0.7, verbose=True)
def mag_to_flux_e_sec(self, mag, band, exptime, nexp): """ Mag to flux (in photoelec/sec) conversion Parameters -------------- mag : float input magnitudes band : str input bands exptime : float input exposure times nexp: int number of exposures Returns ---------- counts : float number of ADU counts e_per_sec : float flux in photoelectron per sec. """ if not hasattr(mag, '__iter__'): wavelen_min, wavelen_max, wavelen_step = self.atmosphere[ band].getWavelenLimits(None, None, None) sed = Sed() sed.setFlatSED() flux0 = sed.calcFluxNorm(mag, self.atmosphere[band]) sed.multiplyFluxNorm(flux0) photParams = PhotometricParameters(exptime=exptime, nexp=nexp) counts = sed.calcADU(bandpass=self.atmosphere[band], photParams=photParams) e_per_sec = counts # counts per sec e_per_sec /= (exptime * nexp) # conversion to pe e_per_sec *= photParams.gain return counts, e_per_sec else: r = [] for m, b, expt, nexpos in zip(mag, band, exptime, nexp): counts, flux_e = self.mag_to_flux_e_sec(m, b, expt, nexpos) r.append((counts, flux_e)) return np.asarray(r)
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 = Sed() sed.readSED_flambda(os.path.join(self.sedDir, 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.setupCCM_ab() sed.addDust(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.setupCCM_ab() sed.addDust(a_int, b_int, A_v=gAv, R_v=gRv) return sed
def ZP_filtre(self, filtre): """ ZP_filtre() : Compute zero point in filter band - platescale is 0.2 arcsec per pixel Tool function implemented by Phillie Gris (IN2P3) """ # extract parameters from lsst_sims photParams = PhotometricParameters(bandpass=filtre) # compute Diameter in meters : D=2*R = 2*sqrt(S/pi) Diameter = 2. * np.sqrt( photParams.effarea * 1.e-4 / np.pi) # diameter in meter # AB flux is 3.6307805477e-20 erg/cm2/s/Hz or 3.6307805477e-16 erg/m2/s/Hz # or 3.6307e-23 J/m2/s/Hz, h=6.626e-34 J.s # What is the meaning of this Cte ???? # especcialy what is 1e36 ? Cte = 3631. * np.pi * Diameter**2 * 2. * photParams.exptime / 4 / h / 1.e36 #print('Telescope::ZP_filtre: hello Cte=',Cte, ' Diam=',Diameter, 'h=',h,' exptime=',photParams.exptime) # What is the meaning of Skyb ????? self.data['Skyb'][filtre] = Cte * np.power( Diameter / 6.5, 2.) * np.power( 2. * photParams.exptime / 30., 2.) * np.power( photParams.platescale, 2.) * np.power( 10., 0.4 * (25. - self.mag_sky[filtre])) * self.Sigmab[filtre] #What is the meaning of Sigmab, Tb, Zb such Zb is used to calculate zero point Zb = 181.8 * np.power(Diameter / 6.5, 2.) * self.Tb[filtre] mbZ = 25. + 2.5 * np.log10(Zb) #filter without atmosphere filtre_trans = self.system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) flatSed = Sed() flatSed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0 = np.power(10., -0.4 * mbZ) flatSed.multiplyFluxNorm(flux0) photParams = PhotometricParameters(bandpass=filtre) counts = flatSed.calcADU( bandpass, photParams=photParams) #number of counts for exptime self.data['zp'][filtre] = mbZ #print('Telescope::ZP_filtre hello',counts/self.photParams.exptime) self.data['counts_zp'][filtre] = counts / 2. * photParams.exptime
def testSignalToNoise(self): """ Test that calcSNR_m5 and calcSNR_sed give similar results """ defaults = LSSTdefaults() photParams = PhotometricParameters() m5 = [] for i in range(len(self.hardwareList)): m5.append(snr.calcM5(self.skySed, self.bpList[i], self.hardwareList[i], photParams, seeing=defaults.seeing(self.filterNameList[i]))) sedDir = lsst.utils.getPackageDir('sims_sed_library') sedDir = os.path.join(sedDir, 'starSED', 'kurucz') fileNameList = os.listdir(sedDir) numpy.random.seed(42) offset = numpy.random.random_sample(len(fileNameList))*2.0 for ix, name in enumerate(fileNameList): if ix>100: break spectrum = Sed() spectrum.readSED_flambda(os.path.join(sedDir, name)) ff = spectrum.calcFluxNorm(m5[2]-offset[ix], self.bpList[2]) spectrum.multiplyFluxNorm(ff) magList = [] controlList = [] magList = [] for i in range(len(self.bpList)): controlList.append(snr.calcSNR_sed(spectrum, self.bpList[i], self.skySed, self.hardwareList[i], photParams, defaults.seeing(self.filterNameList[i]))) magList.append(spectrum.calcMag(self.bpList[i])) testList, gammaList = snr.calcSNR_m5(numpy.array(magList), numpy.array(self.bpList), numpy.array(m5), photParams) for tt, cc in zip(controlList, testList): msg = '%e != %e ' % (tt, cc) self.assertTrue(numpy.abs(tt/cc - 1.0) < 0.001, msg=msg)
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 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 Calc_m5(self, filtre): """ Calc_m5(filtre): Compute m5 or SNR at five sigma Tool function implemented by Phillie Gris (IN2P3) """ # get telescope passband (no atmosphere) filtre_trans = self.system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) # create a Flat sed S_nu from the sky brightness magnitude flatSedb = Sed() flatSedb.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0b = np.power(10., -0.4 * self.mag_sky[filtre]) flatSedb.multiplyFluxNorm(flux0b) # Get LSST photometric parameters photParams = PhotometricParameters(bandpass=filtre) norm = photParams.platescale**2 / 2. * photParams.exptime / photParams.gain # Use LSST sims (SignalToNoise) to calculate M5 with atmosphere or without atmosphere if self.atmos: self.data['m5'][filtre] = SignalToNoise.calcM5( flatSedb, self.atmosphere[filtre], self.system[filtre], photParams=photParams, FWHMeff=self.FWHMeff[filtre]) adu_int = flatSedb.calcADU(bandpass=self.atmosphere[filtre], photParams=photParams) self.data['flux_sky'][filtre] = adu_int * norm else: self.data['m5'][filtre] = SignalToNoise.calcM5( flatSedb, self.system[filtre], self.system[filtre], photParams=photParams, FWHMeff=self.FWHMeff[filtre]) adu_int = flatSedb.calcADU(bandpass=self.system[filtre], photParams=photParams) self.data['flux_sky'][filtre] = adu_int * norm
def testMagError(self): """ Make sure that calcMagError_sed and calcMagError_m5 agree to within 0.001 """ defaults = LSSTdefaults() photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) # find the magnitudes of that spectrum in our bandpasses magList = [] for total in self.bpList: magList.append(spectrum.calcMag(total)) magList = np.array(magList) # try for different normalizations of the skySED for fNorm in np.arange(1.0, 5.0, 1.0): self.skySed.multiplyFluxNorm(fNorm) for total, hardware, filterName, mm in \ zip(self.bpList, self.hardwareList, self.filterNameList, magList): FWHMeff = defaults.FWHMeff(filterName) m5 = snr.calcM5(self.skySed, total, hardware, photParams, FWHMeff=FWHMeff) sigma_sed = snr.calcMagError_sed(spectrum, total, self.skySed, hardware, photParams, FWHMeff=FWHMeff) sigma_m5, gamma = snr.calcMagError_m5(mm, total, m5, photParams) self.assertAlmostEqual(sigma_m5, sigma_sed, 3)
def CalcMyABMagnitudesError_filter(self, band, SkyBrightnessMag, FWHMGeom): """ CalcMyABMagnitudesError_filter(self,band,SkyBrightnessMag,FWHMGeom) - author : Sylvie Dagoret-Campagne - affiliation : LAL/IN2P3/CNRS/FRANCE - date : July 5th 2018 Calculate magnitude errors for one band. Input args: - band : filter band - SkyBrighnessMag : Sky Brighness Magnitude in the band - FWHMGeom : Geometrical PSF in the band """ filtre_atm = self.lsst_atmos[band] filtre_syst = self.lsst_system[band] wavelen_min, wavelen_max, wavelen_step = filtre_syst.getWavelenLimits( None, None, None) #calculation of effective PSF FWHMeff = SignalToNoise.FWHMgeom2FWHMeff(FWHMGeom) photParams = PhotometricParameters(bandpass=band) # create a Flat sed S_nu from the sky brightness magnitude skysed = Sed() skysed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0b = np.power(10., -0.4 * SkyBrightnessMag) skysed.multiplyFluxNorm(flux0b) #calcMagError filled according doc mag_err = SignalToNoise.calcMagError_sed(self.sed, filtre_atm, skysed, filtre_syst, photParams, FWHMeff, verbose=False) return mag_err
def testSignalToNoise(self): """ Test that calcSNR_m5 and calcSNR_sed give similar results """ defaults = LSSTdefaults() photParams = PhotometricParameters() m5 = [] for i in range(len(self.hardwareList)): m5.append( snr.calcM5(self.skySed, self.bpList[i], self.hardwareList[i], photParams, FWHMeff=defaults.FWHMeff(self.filterNameList[i]))) sedDir = os.path.join(lsst.utils.getPackageDir('sims_photUtils'), 'tests/cartoonSedTestData/starSed/') sedDir = os.path.join(sedDir, 'kurucz') fileNameList = os.listdir(sedDir) rng = np.random.RandomState(42) offset = rng.random_sample(len(fileNameList)) * 2.0 for ix, name in enumerate(fileNameList): if ix > 100: break spectrum = Sed() spectrum.readSED_flambda(os.path.join(sedDir, name)) ff = spectrum.calcFluxNorm(m5[2] - offset[ix], self.bpList[2]) spectrum.multiplyFluxNorm(ff) for i in range(len(self.bpList)): control_snr = snr.calcSNR_sed( spectrum, self.bpList[i], self.skySed, self.hardwareList[i], photParams, defaults.FWHMeff(self.filterNameList[i])) mag = spectrum.calcMag(self.bpList[i]) test_snr, gamma = snr.calcSNR_m5(mag, self.bpList[i], m5[i], photParams) self.assertLess((test_snr - control_snr) / control_snr, 0.001)
def testMagError(self): """ Make sure that calcMagError_sed and calcMagError_m5 agree to within 0.001 """ defaults = LSSTdefaults() photParams = PhotometricParameters() #create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) #find the magnitudes of that spectrum in our bandpasses magList = [] for total in self.bpList: magList.append(spectrum.calcMag(total)) magList = numpy.array(magList) #try for different normalizations of the skySED for fNorm in numpy.arange(1.0, 5.0, 1.0): self.skySed.multiplyFluxNorm(fNorm) m5List = [] magSed = [] for total, hardware, filterName in \ zip(self.bpList, self.hardwareList, self.filterNameList): seeing = defaults.seeing(filterName) m5List.append(snr.calcM5(self.skySed, total, hardware, photParams,seeing=seeing)) magSed.append(snr.calcMagError_sed(spectrum, total, self.skySed, hardware, photParams, seeing=seeing)) magSed = numpy.array(magSed) magM5 = snr.calcMagError_m5(magList, self.bpList, numpy.array(m5List), photParams) numpy.testing.assert_array_almost_equal(magM5, magSed, decimal=3)
def get_zp(self, what, band): """ decorator get zero points formula used here are extracted from LSE-40 Parameters --------------- what: str parameter to estimate band: str filter """ photParams = PhotometricParameters(bandpass=band) Diameter = 2. * np.sqrt( photParams.effarea * 1.e-4 / np.pi) # diameter in meter Cte = 3631. * np.pi * Diameter**2 * 2. * photParams.exptime / 4 / h / 1.e36 self.data['Skyb'][band] = Cte*np.power(Diameter/6.5, 2.)\ * np.power(2.*photParams.exptime/30., 2.)\ * np.power(photParams.platescale, 2.)\ * 10.**0.4*(25.-self.mag_sky(band))\ * self.Sigmab(band) Zb = 181.8 * np.power(Diameter / 6.5, 2.) * self.Tb(band) mbZ = 25. + 2.5 * np.log10(Zb) filtre_trans = self.system[band] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) flatSed = Sed() flatSed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0 = np.power(10., -0.4 * mbZ) flatSed.multiplyFluxNorm(flux0) photParams = PhotometricParameters(bandpass=band) # number of counts for exptime counts = flatSed.calcADU(bandpass, photParams=photParams) self.data['zp'][band] = mbZ self.data['counts_zp'][band] = counts / 2. * photParams.exptime
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) ct = 0 for line in starCat.iter_catalog(): starSed = Sed() starSed.readSED_flambda( os.path.join(getPackageDir('sims_sed_library'), defaultSpecMap[line[14]])) imsimband = Bandpass() imsimband.imsimBandpass() fNorm = starSed.calcFluxNorm(line[15], imsimband) starSed.multiplyFluxNorm(fNorm) aV = np.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 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 testSignalToNoise(self): """ Test that calcSNR_m5 and calcSNR_sed give similar results """ defaults = LSSTdefaults() photParams = PhotometricParameters() m5 = [] for i in range(len(self.hardwareList)): m5.append(snr.calcM5(self.skySed, self.bpList[i], self.hardwareList[i], photParams, FWHMeff=defaults.FWHMeff(self.filterNameList[i]))) sedDir = os.path.join(lsst.utils.getPackageDir('sims_photUtils'), 'tests/cartoonSedTestData/starSed/') sedDir = os.path.join(sedDir, 'kurucz') fileNameList = os.listdir(sedDir) rng = np.random.RandomState(42) offset = rng.random_sample(len(fileNameList))*2.0 for ix, name in enumerate(fileNameList): if ix > 100: break spectrum = Sed() spectrum.readSED_flambda(os.path.join(sedDir, name)) ff = spectrum.calcFluxNorm(m5[2]-offset[ix], self.bpList[2]) spectrum.multiplyFluxNorm(ff) for i in range(len(self.bpList)): control_snr = snr.calcSNR_sed(spectrum, self.bpList[i], self.skySed, self.hardwareList[i], photParams, defaults.FWHMeff(self.filterNameList[i])) mag = spectrum.calcMag(self.bpList[i]) test_snr, gamma = snr.calcSNR_m5(mag, self.bpList[i], m5[i], photParams) self.assertLess((test_snr-control_snr)/control_snr, 0.001)
def Calc_m5(self, filtre): filtre_trans = self.throughputs.system[filtre] wavelen_min, wavelen_max, wavelen_step = filtre_trans.getWavelenLimits( None, None, None) bandpass = Bandpass(wavelen=filtre_trans.wavelen, sb=filtre_trans.sb) flatSedb = Sed() flatSedb.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0b = np.power(10., -0.4 * self.mag_sky[filtre]) flatSedb.multiplyFluxNorm(flux0b) if self.atmos: self.data['m5'][filtre] = SignalToNoise.calcM5( flatSedb, self.throughputs.atmosphere[filtre], self.throughputs.system[filtre], photParams=self.photParams, FWHMeff=self.FWHMeff[filtre]) adu_int = flatSedb.calcADU( bandpass=self.throughputs.atmosphere[filtre], photParams=self.photParams) self.data['flux_sky'][ filtre] = adu_int * self.pixel_area / self.expTime[ filtre] / self.gain else: self.data['m5'][filtre] = SignalToNoise.calcM5( flatSedb, self.throughputs.system[filtre], self.throughputs.system[filtre], photParams=self.photParams, FWHMeff=self.FWHMeff[filtre]) adu_int = flatSedb.calcADU( bandpass=self.throughputs.system[filtre], photParams=self.photParams) self.data['flux_sky'][ filtre] = adu_int * self.pixel_area / self.expTime[ filtre] / self.gain
def calcADUwrapper(sedName=None, magNorm=None, redshift=None, internalAv=None, internalRv=None, galacticAv=None, galacticRv=None, bandpass=None): 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.setupCCMab() sed.addCCMDust(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.setupCCMab() sed.addCCMDust(a_int, b_int, A_v=galacticAv, R_v=galacticRv) adu = sed.calcADU(bandpass, photParams=PhotometricParameters()) return adu
def testMagError(self): """ Make sure that calcMagError_sed and calcMagError_m5 agree to within 0.001 """ defaults = LSSTdefaults() photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) # find the magnitudes of that spectrum in our bandpasses magList = [] for total in self.bpList: magList.append(spectrum.calcMag(total)) magList = numpy.array(magList) # try for different normalizations of the skySED for fNorm in numpy.arange(1.0, 5.0, 1.0): self.skySed.multiplyFluxNorm(fNorm) m5List = [] magSed = [] for total, hardware, filterName in zip(self.bpList, self.hardwareList, self.filterNameList): seeing = defaults.seeing(filterName) m5List.append(snr.calcM5(self.skySed, total, hardware, photParams, seeing=seeing)) magSed.append(snr.calcMagError_sed(spectrum, total, self.skySed, hardware, photParams, seeing=seeing)) magSed = numpy.array(magSed) magM5 = snr.calcMagError_m5(magList, self.bpList, numpy.array(m5List), photParams) numpy.testing.assert_array_almost_equal(magM5, magSed, decimal=3)
def CalcMyABMagnitudesErrors(self): """ CalcMyABMagnitudesErrors(self) - author : Sylvie Dagoret-Campagne - affiliation : LAL/IN2P3/CNRS/FRANCE - date : July 4th 2018 Calculate magnitude errors for all bands """ all_magABErr = [] for i, band in enumerate(self.filterlist): filtre_atm = self.lsst_atmos[band] filtre_syst = self.lsst_system[band] wavelen_min, wavelen_max, wavelen_step = filtre_syst.getWavelenLimits( None, None, None) photParams = PhotometricParameters(bandpass=band) FWHMeff = self.data['FWHMeff'][band] # create a Flat sed S_nu from the sky brightness magnitude skysed = Sed() skysed.setFlatSED(wavelen_min, wavelen_max, wavelen_step) flux0b = np.power(10., -0.4 * self.mag_sky[band]) skysed.multiplyFluxNorm(flux0b) #calcMagError filled according doc magerr=SignalToNoise.calcMagError_sed( \ self.sed,filtre_atm,skysed,filtre_syst,photParams,FWHMeff,verbose=False) all_magABErr.append(magerr) return np.array(all_magABErr)
class TestSNRmethods(unittest.TestCase): 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 testMagError(self): """ Make sure that calcMagError_sed and calcMagError_m5 agree to within 0.001 """ defaults = LSSTdefaults() photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) # find the magnitudes of that spectrum in our bandpasses magList = [] for total in self.bpList: magList.append(spectrum.calcMag(total)) magList = numpy.array(magList) # try for different normalizations of the skySED for fNorm in numpy.arange(1.0, 5.0, 1.0): self.skySed.multiplyFluxNorm(fNorm) m5List = [] magSed = [] for total, hardware, filterName in zip(self.bpList, self.hardwareList, self.filterNameList): seeing = defaults.seeing(filterName) m5List.append(snr.calcM5(self.skySed, total, hardware, photParams, seeing=seeing)) magSed.append(snr.calcMagError_sed(spectrum, total, self.skySed, hardware, photParams, seeing=seeing)) magSed = numpy.array(magSed) magM5 = snr.calcMagError_m5(magList, self.bpList, numpy.array(m5List), photParams) numpy.testing.assert_array_almost_equal(magM5, magSed, decimal=3) def testVerboseSNR(self): """ Make sure that calcSNR_sed has everything it needs to run in verbose mode """ defaults = LSSTdefaults() photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) snr.calcSNR_sed( spectrum, self.bpList[0], self.skySed, self.hardwareList[0], photParams, seeing=0.7, verbose=True ) def testSNRexceptions(self): """ test that calcSNR_m5 raises an exception when arguments are not of the right shape. """ photParams = PhotometricParameters() shortGamma = numpy.array([1.0, 1.0]) shortMagnitudes = numpy.array([22.0, 23.0]) magnitudes = 22.0 * numpy.ones(6) self.assertRaises(RuntimeError, snr.calcSNR_m5, magnitudes, self.bpList, shortMagnitudes, photParams) self.assertRaises(RuntimeError, snr.calcSNR_m5, shortMagnitudes, self.bpList, magnitudes, photParams) self.assertRaises( RuntimeError, snr.calcSNR_m5, magnitudes, self.bpList, magnitudes, photParams, gamma=shortGamma ) signalToNoise, gg = snr.calcSNR_m5(magnitudes, self.bpList, magnitudes, photParams) def testSignalToNoise(self): """ Test that calcSNR_m5 and calcSNR_sed give similar results """ defaults = LSSTdefaults() photParams = PhotometricParameters() m5 = [] for i in range(len(self.hardwareList)): m5.append( snr.calcM5( self.skySed, self.bpList[i], self.hardwareList[i], photParams, seeing=defaults.seeing(self.filterNameList[i]), ) ) sedDir = lsst.utils.getPackageDir("sims_sed_library") sedDir = os.path.join(sedDir, "starSED", "kurucz") fileNameList = os.listdir(sedDir) numpy.random.seed(42) offset = numpy.random.random_sample(len(fileNameList)) * 2.0 for ix, name in enumerate(fileNameList): if ix > 100: break spectrum = Sed() spectrum.readSED_flambda(os.path.join(sedDir, name)) ff = spectrum.calcFluxNorm(m5[2] - offset[ix], self.bpList[2]) spectrum.multiplyFluxNorm(ff) magList = [] controlList = [] magList = [] for i in range(len(self.bpList)): controlList.append( snr.calcSNR_sed( spectrum, self.bpList[i], self.skySed, self.hardwareList[i], photParams, defaults.seeing(self.filterNameList[i]), ) ) magList.append(spectrum.calcMag(self.bpList[i])) testList, gammaList = snr.calcSNR_m5( numpy.array(magList), numpy.array(self.bpList), numpy.array(m5), photParams ) for tt, cc in zip(controlList, testList): msg = "%e != %e " % (tt, cc) self.assertTrue(numpy.abs(tt / cc - 1.0) < 0.001, msg=msg) def testSystematicUncertainty(self): """ Test that systematic uncertainty is added correctly. """ sigmaSys = 0.002 m5 = [23.5, 24.3, 22.1, 20.0, 19.5, 21.7] photParams = PhotometricParameters(sigmaSys=sigmaSys) obs_metadata = ObservationMetaData( unrefractedRA=23.0, unrefractedDec=45.0, m5=m5, bandpassName=self.filterNameList ) magnitudes = [] for bp in self.bpList: mag = self.starSED.calcMag(bp) magnitudes.append(mag) skySedList = [] for bp, hardware, filterName in zip(self.bpList, self.hardwareList, self.filterNameList): skyDummy = Sed() skyDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir("throughputs"), "baseline", "darksky.dat")) normalizedSkyDummy = setM5( obs_metadata.m5[filterName], skyDummy, bp, hardware, seeing=LSSTdefaults().seeing(filterName), photParams=photParams, ) skySedList.append(normalizedSkyDummy) sigmaList = snr.calcMagError_m5(numpy.array(magnitudes), numpy.array(self.bpList), numpy.array(m5), photParams) for i in range(len(self.bpList)): snrat = snr.calcSNR_sed( self.starSED, self.bpList[i], skySedList[i], self.hardwareList[i], seeing=LSSTdefaults().seeing(self.filterNameList[i]), photParams=PhotometricParameters(), ) testSNR, gamma = snr.calcSNR_m5( numpy.array([magnitudes[i]]), [self.bpList[i]], numpy.array([m5[i]]), photParams=PhotometricParameters(sigmaSys=0.0), ) self.assertAlmostEqual( snrat, testSNR[0], 10, msg="failed on calcSNR_m5 test %e != %e " % (snrat, testSNR[0]) ) control = numpy.sqrt(numpy.power(snr.magErrorFromSNR(testSNR), 2) + numpy.power(sigmaSys, 2)) msg = "%e is not %e; failed" % (sigmaList[i], control) self.assertAlmostEqual(sigmaList[i], control, 10, msg=msg) def testNoSystematicUncertainty(self): """ Test that systematic uncertainty is handled correctly when set to None. """ m5 = [23.5, 24.3, 22.1, 20.0, 19.5, 21.7] photParams = PhotometricParameters(sigmaSys=0.0) obs_metadata = ObservationMetaData( unrefractedRA=23.0, unrefractedDec=45.0, m5=m5, bandpassName=self.filterNameList ) magnitudes = [] for bp in self.bpList: mag = self.starSED.calcMag(bp) magnitudes.append(mag) skySedList = [] for bp, hardware, filterName in zip(self.bpList, self.hardwareList, self.filterNameList): skyDummy = Sed() skyDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir("throughputs"), "baseline", "darksky.dat")) normalizedSkyDummy = setM5( obs_metadata.m5[filterName], skyDummy, bp, hardware, seeing=LSSTdefaults().seeing(filterName), photParams=photParams, ) skySedList.append(normalizedSkyDummy) sigmaList = snr.calcMagError_m5(numpy.array(magnitudes), numpy.array(self.bpList), numpy.array(m5), photParams) for i in range(len(self.bpList)): snrat = snr.calcSNR_sed( self.starSED, self.bpList[i], skySedList[i], self.hardwareList[i], seeing=LSSTdefaults().seeing(self.filterNameList[i]), photParams=PhotometricParameters(), ) testSNR, gamma = snr.calcSNR_m5( numpy.array([magnitudes[i]]), [self.bpList[i]], numpy.array([m5[i]]), photParams=PhotometricParameters(sigmaSys=0.0), ) self.assertAlmostEqual( snrat, testSNR[0], 10, msg="failed on calcSNR_m5 test %e != %e " % (snrat, testSNR[0]) ) control = snr.magErrorFromSNR(testSNR) msg = "%e is not %e; failed" % (sigmaList[i], control) self.assertAlmostEqual(sigmaList[i], control, 10, msg=msg)
print "" print "Without any scaling of the SED, the magnitude is %.4f" %(mag) # That was probably pretty small, right? Maybe we actually know what # magnitude we expect this source to have in this bandpass, and then want to scale # the SED to that appropriate magnitude (and then calculate the magnitudes once it's # scaled properly, in other bandpasses). mag_desired = 24.5 print "Now going to apply a scaling factor to the SED to set magnitude to %.4f" %(mag_desired) # Calculate the scaling factor. fluxnorm = star.calcFluxNorm(mag_desired, rband) # Apply the scaling factor. star.multiplyFluxNorm(fluxnorm) # Try the magnitude calculation again. mag = star.calcMag(rband) print "After scaling, magnitude of SED is now %.4f (desired magnitude was %.4f)" %(mag, mag_desired) # And let's calculate what the expected photon counts for LSST would be. counts = star.calcADU(rband, expTime=30) print "This would correspond to roughly %f counts in the LSST focal plane, in a 30s exposure." %(counts) # For fun, let's see what else can happen. ebv = 0.5 print "" print "Let's try adding %.2f E(B-V) dust extinction to this star." %(ebv) a, b = star.setupCCMab()
# create the a,b arrays for all the gals (because we resampled the gals onto the # same wavelength range we can just calculate a/b once, and this is slow) a_gal, b_gal = gals[galaxykeys[0]].setupCCMab() # pretend we want to read mags into an array .. you could just as easily put it into a # dictionary or list, with small variations in the code mags = n.empty(len(galaxykeys), dtype='float') for i in range(len(galaxykeys)): # make a copy of the original SED if you want to 'reuse' the SED for multiple magnitude # calculations with various fluxnorms, redshifts and dusts tmpgal = Sed(wavelen=gals[galaxykeys[i]].wavelen, flambda=gals[galaxykeys[i]].flambda) # add the dust internal to the distant galaxy tmpgal.addCCMDust(a_gal, b_gal, ebv=ebv_gal[i]) # redshift the galaxy tmpgal.redshiftSED(redshifts[i], dimming=False) # add the dust from our milky way - have to recalculate a/b because now wavelenghts # for each galaxy are *different* a_mw, b_mw = tmpgal.setupCCMab() tmpgal.addCCMDust(a_mw, b_mw, ebv=ebv_mw[i]) tmpgal.multiplyFluxNorm(fluxnorm[i]) mags[i] = tmpgal.calcMag(rband) # show results print "#sedname fluxnorm redshift ebv_gal ebv_mw magnitude " for i in range(len(galaxykeys)): print "%s %.5g %.3f %.5f %.5f %.5f" %(galaxykeys[i], fluxnorm[i], redshifts[i], ebv_gal[i], ebv_mw[i], mags[i])
def _quiescentMagnitudeGetter(self, bandpassDict, columnNameList, bandpassTag='lsst'): """ Method that actually does the work calculating magnitudes for solar system objects. Because solar system objects have no dust extinction, this method works by loading each unique Sed once, normalizing it, calculating its magnitudes in the desired bandpasses, and then storing the normalizing magnitudes and the bandpass magnitudes in a dict. Magnitudes for subsequent objects with identical Seds will be calculated by adding an offset to the magnitudes. The offset is determined by comparing normalizing magnitues. @param [in] bandpassDict is an instantiation of BandpassDict representing the bandpasses to be integrated over @param [in] columnNameList is a list of the names of the columns being calculated by this getter @param [in] bandpassTag (optional) is a string indicating the name of the bandpass system (i.e. 'lsst', 'sdss', etc.). This is in case the user wants to calculate the magnitudes in multiple systems simultaneously. In that case, the dict will store magnitudes for each Sed in each magnitude system separately. @param [out] a numpy array of magnitudes corresponding to bandpassDict. """ # figure out which of these columns we are actually calculating indices = [ii for ii, name in enumerate(columnNameList) if name in self._actually_calculated_columns] if len(indices) == len(columnNameList): indices = None if not hasattr(self, '_ssmMagDict'): self._ssmMagDict = {} self._ssmMagNormDict = {} self._file_dir = getPackageDir('sims_sed_library') self._spec_map = defaultSpecMap self._normalizing_bandpass = Bandpass() self._normalizing_bandpass.imsimBandpass() sedNameList = self.column_by_name('sedFilename') magNormList = self.column_by_name('magNorm') if len(sedNameList)==0: # need to return something when InstanceCatalog goes through # it's "dry run" to determine what columns are required from # the database return np.zeros((len(bandpassDict.keys()),0)) magListOut = [] for sedName, magNorm in zip(sedNameList, magNormList): magTag = bandpassTag+'_'+sedName if sedName not in self._ssmMagNormDict or magTag not in self._ssmMagDict: dummySed = Sed() dummySed.readSED_flambda(os.path.join(self._file_dir, self._spec_map[sedName])) fnorm = dummySed.calcFluxNorm(magNorm, self._normalizing_bandpass) dummySed.multiplyFluxNorm(fnorm) magList = bandpassDict.magListForSed(dummySed, indices=indices) self._ssmMagDict[magTag] = magList self._ssmMagNormDict[sedName] = magNorm else: dmag = magNorm - self._ssmMagNormDict[sedName] magList = self._ssmMagDict[magTag] + dmag magListOut.append(magList) return np.array(magListOut).transpose()
response = gaia_response(restore_file='gaia_response.npz') # response = gaia_response(restore_file='gaia_response_nonoise.npz') filename = 'starSED/wDs/bergeron_14000_85.dat_14200.gz' imsimBand = Bandpass() imsimBand.imsimBandpass() sed_dir = getPackageDir('sims_sed_library') filepath = os.path.join(sed_dir, filename) wd = Sed() wd.readSED_flambda(filepath) magnorm = 16 fNorm = wd.calcFluxNorm(magnorm, imsimBand) wd.multiplyFluxNorm(fNorm) throughPath = os.path.join(getPackageDir('throughputs'), 'baseline') lsstKeys = ['u', 'g', 'r', 'i', 'z', 'y'] # lsstKeys = ['r'] 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 # Generate a GAIA observation
# same wavelength range we can just calculate a/b once, and this is slow) a, b = stars[starskeys[0]].setupCCMab() # pretend we want to read mags into an array .. you could just as easily put it into a # dictionary or list, with small variations in the code mags = n.empty(len(starskeys), dtype="float") mags2 = n.empty(len(starskeys), dtype="float") sedlist = [] for i in range(len(starskeys)): # make a copy of the original SED *if* you want to 'reuse' the SED for multiple magnitude # calculations with various fluxnorms and dust applications (otherwise just use the object # you instantiated above) tmpstar = Sed(wavelen=stars[starskeys[i]].wavelen, flambda=stars[starskeys[i]].flambda) tmpstar.addCCMDust(a, b, ebv=ebv[i]) tmpstar.multiplyFluxNorm(fluxnorm[i]) mags[i] = tmpstar.calcMag(rband) # This is for showing an example of the manyMagCalc function on bandpass sedlist.append(tmpstar) # Now, pretend we're actually wanting to calculate the magnitude in multiple bandpasses. # (ignore the part that uses exampleBandpass.dat as the source .. you would replace that with # rootdir + "total_" + filter where filter is a member of lsstfilterlist lsstfilterlist = ["u", "g", "r", "i", "z", "y"] lsst = {} rootdir = "./" for filter in lsstfilterlist: lsst[filter] = Bandpass() lsst[filter].readThroughput(rootdir + "exampleBandpass.dat") # you have to do this now - sbToPhi to use the multi-mag calc
class TestSNRmethods(unittest.TestCase): 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 testMagError(self): """ Make sure that calcMagError_sed and calcMagError_m5 agree to within 0.001 """ defaults = LSSTdefaults() photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) # find the magnitudes of that spectrum in our bandpasses magList = [] for total in self.bpList: magList.append(spectrum.calcMag(total)) magList = np.array(magList) # try for different normalizations of the skySED for fNorm in np.arange(1.0, 5.0, 1.0): self.skySed.multiplyFluxNorm(fNorm) for total, hardware, filterName, mm in \ zip(self.bpList, self.hardwareList, self.filterNameList, magList): FWHMeff = defaults.FWHMeff(filterName) m5 = snr.calcM5(self.skySed, total, hardware, photParams, FWHMeff=FWHMeff) sigma_sed = snr.calcMagError_sed(spectrum, total, self.skySed, hardware, photParams, FWHMeff=FWHMeff) sigma_m5, gamma = snr.calcMagError_m5(mm, total, m5, photParams) self.assertAlmostEqual(sigma_m5, sigma_sed, 3) def testVerboseSNR(self): """ Make sure that calcSNR_sed has everything it needs to run in verbose mode """ photParams = PhotometricParameters() # create a cartoon spectrum to test on spectrum = Sed() spectrum.setFlatSED() spectrum.multiplyFluxNorm(1.0e-9) snr.calcSNR_sed(spectrum, self.bpList[0], self.skySed, self.hardwareList[0], photParams, FWHMeff=0.7, verbose=True) def testSignalToNoise(self): """ Test that calcSNR_m5 and calcSNR_sed give similar results """ defaults = LSSTdefaults() photParams = PhotometricParameters() m5 = [] for i in range(len(self.hardwareList)): m5.append(snr.calcM5(self.skySed, self.bpList[i], self.hardwareList[i], photParams, FWHMeff=defaults.FWHMeff(self.filterNameList[i]))) sedDir = os.path.join(lsst.utils.getPackageDir('sims_photUtils'), 'tests/cartoonSedTestData/starSed/') sedDir = os.path.join(sedDir, 'kurucz') fileNameList = os.listdir(sedDir) rng = np.random.RandomState(42) offset = rng.random_sample(len(fileNameList))*2.0 for ix, name in enumerate(fileNameList): if ix > 100: break spectrum = Sed() spectrum.readSED_flambda(os.path.join(sedDir, name)) ff = spectrum.calcFluxNorm(m5[2]-offset[ix], self.bpList[2]) spectrum.multiplyFluxNorm(ff) for i in range(len(self.bpList)): control_snr = snr.calcSNR_sed(spectrum, self.bpList[i], self.skySed, self.hardwareList[i], photParams, defaults.FWHMeff(self.filterNameList[i])) mag = spectrum.calcMag(self.bpList[i]) test_snr, gamma = snr.calcSNR_m5(mag, self.bpList[i], m5[i], photParams) self.assertLess((test_snr-control_snr)/control_snr, 0.001) def testSystematicUncertainty(self): """ Test that systematic uncertainty is added correctly. """ sigmaSys = 0.002 m5_list = [23.5, 24.3, 22.1, 20.0, 19.5, 21.7] photParams = PhotometricParameters(sigmaSys=sigmaSys) obs_metadata = ObservationMetaData(pointingRA=23.0, pointingDec=45.0, m5=m5_list, bandpassName=self.filterNameList) magnitude_list = [] for bp in self.bpList: mag = self.starSED.calcMag(bp) magnitude_list.append(mag) for bp, hardware, filterName, mm, m5 in \ zip(self.bpList, self.hardwareList, self.filterNameList, magnitude_list, m5_list): skyDummy = Sed() skyDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline', 'darksky.dat')) normalizedSkyDummy = setM5(obs_metadata.m5[filterName], skyDummy, bp, hardware, FWHMeff=LSSTdefaults().FWHMeff(filterName), photParams=photParams) sigma, gamma = snr.calcMagError_m5(mm, bp, m5, photParams) snrat = snr.calcSNR_sed(self.starSED, bp, normalizedSkyDummy, hardware, FWHMeff=LSSTdefaults().FWHMeff(filterName), photParams=PhotometricParameters()) testSNR, gamma = snr.calcSNR_m5(mm, bp, m5, photParams=PhotometricParameters(sigmaSys=0.0)) self.assertAlmostEqual(snrat, testSNR, 10, msg = 'failed on calcSNR_m5 test %e != %e ' % (snrat, testSNR)) control = np.sqrt(np.power(snr.magErrorFromSNR(testSNR), 2) + np.power(sigmaSys, 2)) msg = '%e is not %e; failed' % (sigma, control) self.assertAlmostEqual(sigma, control, 10, msg=msg) def testNoSystematicUncertainty(self): """ Test that systematic uncertainty is handled correctly when set to None. """ m5_list = [23.5, 24.3, 22.1, 20.0, 19.5, 21.7] photParams = PhotometricParameters(sigmaSys=0.0) obs_metadata = ObservationMetaData(pointingRA=23.0, pointingDec=45.0, m5=m5_list, bandpassName=self.filterNameList) magnitude_list = [] for bp in self.bpList: mag = self.starSED.calcMag(bp) magnitude_list.append(mag) for bp, hardware, filterName, mm, m5 in \ zip(self.bpList, self.hardwareList, self.filterNameList, magnitude_list, m5_list): skyDummy = Sed() skyDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline', 'darksky.dat')) normalizedSkyDummy = setM5(obs_metadata.m5[filterName], skyDummy, bp, hardware, FWHMeff=LSSTdefaults().FWHMeff(filterName), photParams=photParams) sigma, gamma = snr.calcMagError_m5(mm, bp, m5, photParams) snrat = snr.calcSNR_sed(self.starSED, bp, normalizedSkyDummy, hardware, FWHMeff=LSSTdefaults().FWHMeff(filterName), photParams=PhotometricParameters()) testSNR, gamma = snr.calcSNR_m5(mm, bp, m5, photParams=PhotometricParameters(sigmaSys=0.0)) self.assertAlmostEqual(snrat, testSNR, 10, msg = 'failed on calcSNR_m5 test %e != %e ' % (snrat, testSNR)) control = snr.magErrorFromSNR(testSNR) msg = '%e is not %e; failed' % (sigma, control) self.assertAlmostEqual(sigma, control, 10, msg=msg) def testFWHMconversions(self): FWHMeff = 0.8 FWHMgeom = snr.FWHMeff2FWHMgeom(FWHMeff) self.assertEqual(FWHMgeom, (0.822*FWHMeff+0.052)) FWHMgeom = 0.8 FWHMeff = snr.FWHMgeom2FWHMeff(FWHMgeom) self.assertEqual(FWHMeff, (FWHMgeom-0.052)/0.822) def testSNR_arr(self): """ Test that calcSNR_m5 works on numpy arrays of magnitudes """ rng = np.random.RandomState(17) mag_list = rng.random_sample(100)*5.0 + 15.0 photParams = PhotometricParameters() bp = self.bpList[0] m5 = 24.0 control_list = [] for mm in mag_list: ratio, gamma = snr.calcSNR_m5(mm, bp, m5, photParams) control_list.append(ratio) control_list = np.array(control_list) test_list, gamma = snr.calcSNR_m5(mag_list, bp, m5, photParams) np.testing.assert_array_equal(control_list, test_list) def testError_arr(self): """ Test that calcMagError_m5 works on numpy arrays of magnitudes """ rng = np.random.RandomState(17) mag_list = rng.random_sample(100)*5.0 + 15.0 photParams = PhotometricParameters() bp = self.bpList[0] m5 = 24.0 control_list = [] for mm in mag_list: sig, gamma = snr.calcMagError_m5(mm, bp, m5, photParams) control_list.append(sig) control_list = np.array(control_list) test_list, gamma = snr.calcMagError_m5(mag_list, bp, m5, photParams) np.testing.assert_array_equal(control_list, test_list)
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)
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 get_TotalMags(result, bandpasses=('u','g','r','i','z','y')): datadir = os.environ.get("SIMS_SED_LIBRARY_DIR") tpath = os.getenv('LSST_THROUGHPUTS_DEFAULT') bands = {"u":None, "g":None, "r":None, "i":None, "z":None, "y":None} for k in bands: bands[k] = Bandpass() bands[k].readThroughput(os.path.join(tpath, "total_%s.dat"%k)) # Set up phi, the wavelength-normalized system response for each filter, # for each bandpass for manyMagCalc method. bplist = [] for f in ['u','g','r','i','z','y']: bands[f].sbTophi() bplist.append(bands[f]) ids = result['galid'] diskfile = result['sedFilenameDisk'] bulgefile = result['sedFilenameBulge'] agnfile = result['sedFilenameAgn'] diskmn = result['magNormDisk'] bulgemn = result['magNormBulge'] agnmn = result['magNormAgn'] bulgeAv = result['internalAvBulge'] diskAv = result['internalAvDisk'] redshift = result['redshift'] imsimband = Bandpass() imsimband.imsimBandpass() sedDict = {} retMags = dict([(k, []) for k in bands]) a_int = None b_int = None tmpwavelen = None for id, df, dm, dav, bf, bm, bav, af, am, z in zip(ids, diskfile, diskmn, diskAv, bulgefile, bulgemn, bulgeAv, agnfile, agnmn, redshift): tmpflux = None for comp in ((df, dm, dav, 'galaxySED', False), (bf, bm, bav, 'galaxySED', False), (af, am, None, 'agnSED', True)): #Zero out the AGN contribution #for comp in ((df, dm, dav, 'galaxySED', False), (bf, bm, bav, 'galaxySED', False), (af, 99.99, None, 'agnSED', True)): if not comp[0] == u'None': if sedDict.has_key(comp[0]): sed = copy.deepcopy(sedDict[comp[0]]) else: sed = Sed() print os.path.join(datadir,comp[3],comp[0]) sed.readSED_flambda(os.path.join(datadir,comp[3],comp[0])) if comp[4]: sed.resampleSED(wavelen_match=tmpwavelen) sedDict[comp[0]] = sed if a_int is None: phiarray, dlambda = sed.setupPhiArray(bplist) a_int, b_int = sed.setupCCMab() #Careful, this assumes that a disk or bulge sed is read #before any agn sed tmpwavelen = sed.wavelen fNorm = sed.calcFluxNorm(comp[1], imsimband) sed.multiplyFluxNorm(fNorm) #I guess this assumes rv=3.1?? if comp[2]: sed.addCCMDust(a_int, b_int, A_v=comp[2]) wavelenArr=sed.wavelen if tmpflux is None: tmpflux = sed.flambda else: tmpflux += sed.flambda newgal = Sed(wavelen=wavelenArr, flambda=tmpflux) #a_mw, b_mw = sed.setupCCMab() #sed.addCCMDust(a_mw, b_mw, A_v=mwav) newgal.redshiftSED(z, dimming=True) newgal.resampleSED(wavelen_match=bplist[0].wavelen) newgal.flambdaTofnu() mags = newgal.manyMagCalc(phiarray, dlambda) for i,k in enumerate(['u','g','r','i','z','y']): retMags[k].append(mags[i]) return retMags
def calcM5(hardware, system, atmos, title="m5"): effarea = np.pi * (6.423 / 2.0 * 100.0) ** 2 photParams = PhotometricParameters(effarea=effarea) lsstDefaults = LSSTdefaults() darksky = Sed() darksky.readSED_flambda(os.path.join("../siteProperties", "darksky.dat")) flatSed = Sed() flatSed.setFlatSED() m5 = {} sourceCounts = {} skyCounts = {} skyMag = {} gamma = {} for f in system: m5[f] = SignalToNoise.calcM5(darksky, system[f], hardware[f], photParams, FWHMeff=lsstDefaults.FWHMeff(f)) fNorm = flatSed.calcFluxNorm(m5[f], system[f]) flatSed.multiplyFluxNorm(fNorm) sourceCounts[f] = flatSed.calcADU(system[f], photParams=photParams) # Calculate the Skycounts expected in this bandpass. skyCounts[f] = darksky.calcADU(hardware[f], photParams=photParams) * photParams.platescale ** 2 # Calculate the sky surface brightness. skyMag[f] = darksky.calcMag(hardware[f]) # Calculate the gamma value. gamma[f] = SignalToNoise.calcGamma(system[f], m5[f], photParams) print title print "Filter m5 SourceCounts SkyCounts SkyMag Gamma" for f in ("u", "g", "r", "i", "z", "y"): print "%s %.2f %.1f %.2f %.2f %.6f" % (f, m5[f], sourceCounts[f], skyCounts[f], skyMag[f], gamma[f]) # Show what these look like individually (add sky & m5 limits on throughput curves) plt.figure() ax = plt.gca() # Add dark sky ax2 = ax.twinx() plt.sca(ax2) skyab = -2.5 * np.log10(darksky.fnu) - darksky.zp ax2.plot(darksky.wavelen, skyab, "k-", linewidth=0.8, label="Dark sky mags") ax2.set_ylabel("AB mags") ax2.set_ylim(24, 14) plt.sca(ax) # end of dark sky handles = [] for f in filterlist: plt.plot(system[f].wavelen, system[f].sb, color=filtercolors[f], linewidth=2) myline = mlines.Line2D( [], [], color=filtercolors[f], linestyle="-", linewidth=2, label="%s: m5 %.1f (sky %.1f)" % (f, m5[f], skyMag[f]), ) handles.append(myline) plt.plot(atmos.wavelen, atmos.sb, "k:", label="Atmosphere, X=1.0 with aerosols") # Add legend for dark sky. myline = mlines.Line2D([], [], color="k", linestyle="-", label="Dark sky AB mags") handles.append(myline) # end of dark sky legend line plt.legend(loc=(0.01, 0.69), handles=handles, fancybox=True, numpoints=1, fontsize="small") plt.ylim(0, 1) plt.xlim(300, 1100) plt.xlabel("Wavelength (nm)") plt.ylabel("Fractional Throughput Response") if title == "Vendor combo": title = "" plt.title("System total response curves %s" % (title)) plt.savefig("../plots/system+sky" + title + ".png", format="png", dpi=600) return m5
def testGalaxyPhotometricUncertainties(self): """ Test in the case of a catalog of galaxies """ lsstDefaults = LSSTdefaults() phot = PhotometryGalaxies() galDB = testGalaxyTileDBObj(driver=self.driver, host=self.host, database=self.dbName) galCat = testGalaxyCatalog(galDB, obs_metadata=self.obs_metadata) imsimband = Bandpass() imsimband.imsimBandpass() ct = 0 for line in galCat.iter_catalog(): bulgeSedName = line[50] diskSedName = line[51] agnSedName = line[52] magNormBulge = line[53] magNormDisk = line[54] magNormAgn = line[55] avBulge = line[56] avDisk = line[57] redshift = line[58] bulgeSed = Sed() bulgeSed.readSED_flambda(os.path.join(lsst.utils.getPackageDir('sims_sed_library'), defaultSpecMap[bulgeSedName])) fNorm=bulgeSed.calcFluxNorm(magNormBulge, imsimband) bulgeSed.multiplyFluxNorm(fNorm) diskSed = Sed() diskSed.readSED_flambda(os.path.join(lsst.utils.getPackageDir('sims_sed_library'), defaultSpecMap[diskSedName])) fNorm = diskSed.calcFluxNorm(magNormDisk, imsimband) diskSed.multiplyFluxNorm(fNorm) agnSed = Sed() agnSed.readSED_flambda(os.path.join(lsst.utils.getPackageDir('sims_sed_library'), defaultSpecMap[agnSedName])) fNorm = agnSed.calcFluxNorm(magNormAgn, imsimband) agnSed.multiplyFluxNorm(fNorm) a_int, b_int = bulgeSed.setupCCMab() bulgeSed.addCCMDust(a_int, b_int, A_v=avBulge) a_int, b_int = diskSed.setupCCMab() diskSed.addCCMDust(a_int, b_int, A_v=avDisk) bulgeSed.redshiftSED(redshift, dimming=True) diskSed.redshiftSED(redshift, dimming=True) agnSed.redshiftSED(redshift, dimming=True) bulgeSed.resampleSED(wavelen_match=self.totalBandpasses[0].wavelen) diskSed.resampleSED(wavelen_match=bulgeSed.wavelen) agnSed.resampleSED(wavelen_match=bulgeSed.wavelen) numpy.testing.assert_almost_equal(bulgeSed.wavelen, diskSed.wavelen) numpy.testing.assert_almost_equal(bulgeSed.wavelen, agnSed.wavelen) fl = bulgeSed.flambda + diskSed.flambda + agnSed.flambda totalSed = Sed(wavelen=bulgeSed.wavelen, flambda=fl) sedList = [totalSed, bulgeSed, diskSed, agnSed] for i, spectrum in enumerate(sedList): if i==0: msgroot = 'failed on total' elif i==1: msgroot = 'failed on bulge' elif i==2: msgroot = 'failed on disk' elif i==3: msgroot = 'failed on agn' for j, b in enumerate(self.bandpasses): controlSigma = calcMagError_sed(spectrum, self.totalBandpasses[j], self.skySeds[j], self.hardwareBandpasses[j], FWHMeff=lsstDefaults.FWHMeff(b), photParams=PhotometricParameters()) testSigma = line[26+(i*6)+j] msg = '%e neq %e; ' % (testSigma, controlSigma) + msgroot self.assertAlmostEqual(testSigma, controlSigma, 10, msg=msg) ct += 1 self.assertGreater(ct, 0)
def _calculateGalSimSeds(self): """ Apply any physical corrections to the objects' SEDS (redshift them, apply dust, etc.). Return a list of Sed objects containing the SEDS """ sedList = [] actualSEDnames = self.column_by_name('sedFilepath') redshift = self.column_by_name('redshift') internalAv = self.column_by_name('internalAv') internalRv = self.column_by_name('internalRv') galacticAv = self.column_by_name('galacticAv') galacticRv = self.column_by_name('galacticRv') magNorm = self.column_by_name('magNorm') #for setting magNorm imsimband = Bandpass() imsimband.imsimBandpass() outputNames=[] for (sedName, zz, iAv, iRv, gAv, gRv, norm) in \ zip(actualSEDnames, redshift, internalAv, internalRv, galacticAv, galacticRv, magNorm): if is_null(sedName): sedList.append(None) else: if sedName in self.uniqueSeds: #we have already read in this file; no need to do it again sed = Sed(wavelen=self.uniqueSeds[sedName].wavelen, flambda=self.uniqueSeds[sedName].flambda, fnu=self.uniqueSeds[sedName].fnu, name=self.uniqueSeds[sedName].name) else: #load the SED of the object sed = Sed() sedFile = os.path.join(self.sedDir, sedName) sed.readSED_flambda(sedFile) flambdaCopy = copy.deepcopy(sed.flambda) #If the SED is zero inside of the bandpass, GalSim raises an error. #This sets a minimum flux value of 1.0e-30 so that the SED is never technically #zero inside of the bandpass. sed.flambda = numpy.array([ff if ff>1.0e-30 else 1.0e-30 for ff in flambdaCopy]) sed.fnu = None #copy the unnormalized file to uniqueSeds so we don't have to read it in again sedCopy = Sed(wavelen=sed.wavelen, flambda=sed.flambda, fnu=sed.fnu, name=sed.name) self.uniqueSeds[sedName] = sedCopy #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) a_int, b_int = sed.setupCCMab() sed.addCCMDust(a_int, b_int, A_v=gAv, R_v=gRv) sedList.append(sed) return sedList
np.savetxt('magNorm_list_sn.txt', magNorm_array) np.savetxt('av_list_sn.txt', av_array) np.savetxt('rv_list_sn.txt', rv_array) test_bandpassDict = BandpassDict.loadTotalBandpassesFromFiles() imsimband = Bandpass() imsimband.imsimBandpass() mag_norm_glsne = [] for i, idx in list(enumerate(keep_rows)): if i % 10000 == 0: print(i, idx) test_sed = Sed() test_sed.readSED_flambda(os.path.join(str(os.environ['SIMS_SED_LIBRARY_DIR']), sed_name_array[i])) fnorm = test_sed.calcFluxNorm(dc2_df_system['lensgal_mi'].iloc[idx], test_bandpassDict['i']) test_sed.multiplyFluxNorm(fnorm) magNorm_diff = magNorm_array[3, i] - test_sed.calcMag(imsimband) mag_norm_glsne.append(magNorm_array[:,i] - magNorm_diff) mag_norm_glsne = np.array(mag_norm_glsne) results_dict = {} print(len(keep_rows), len(gcr_glsn_match[:, 0])) for keep_idx in range(len(keep_rows)): results_dict[str(dc2_df_system['sysno'].iloc[keep_rows[keep_idx]])] = {'z':gcr_glsn_match[:, 0][keep_idx], 'sed_name':sed_name_array[keep_idx], 'magNorm':mag_norm_glsne[keep_idx], 'lens_av':av_array[keep_idx], 'lens_rv':rv_array[keep_idx]} keep_systems = dc2_df_system['sysno'].iloc[keep_rows].values
def calc_adu(mag, bandpass): sed = Sed() sed.setFlatSED() fluxNorm = sed.calcFluxNorm(mag, bandpass) sed.multiplyFluxNorm(fluxNorm) return sed.calcADU(bandpass, fake_phot_params())
def calcM5s(hardware, system, atmos, title='m5'): photParams = PhotometricParameters() lsstDefaults = LSSTdefaults() darksky = Sed() darksky.readSED_flambda(os.path.join(os.getenv('SYSENG_THROUGHPUTS_DIR'), 'siteProperties', 'darksky.dat')) flatSed = Sed() flatSed.setFlatSED() m5 = {} sourceCounts = {} skyCounts = {} skyMag = {} gamma = {} for f in system: m5[f] = SignalToNoise.calcM5(darksky, system[f], hardware[f], photParams, seeing=lsstDefaults.seeing(f)) fNorm = flatSed.calcFluxNorm(m5[f], system[f]) flatSed.multiplyFluxNorm(fNorm) sourceCounts[f] = flatSed.calcADU(system[f], photParams=photParams) # Calculate the Skycounts expected in this bandpass. skyCounts[f] = darksky.calcADU(hardware[f], photParams=photParams) * photParams.platescale**2 # Calculate the sky surface brightness. skyMag[f] = darksky.calcMag(hardware[f]) # Calculate the gamma value. gamma[f] = SignalToNoise.calcGamma(system[f], m5[f], photParams) print title print 'Filter m5 SourceCounts SkyCounts SkyMag Gamma' for f in ('u', 'g' ,'r', 'i', 'z', 'y'): print '%s %.2f %.1f %.2f %.2f %.6f' %(f, m5[f], sourceCounts[f], skyCounts[f], skyMag[f], gamma[f]) # Show what these look like individually (add sky & m5 limits on throughput curves) plt.figure() ax = plt.gca() # Add dark sky ax2 = ax.twinx() plt.sca(ax2) skyab = -2.5*np.log10(darksky.fnu) - darksky.zp ax2.plot(darksky.wavelen, skyab, 'k-', linewidth=0.8, label='Dark sky mags') ax2.set_ylabel('AB mags') ax2.set_ylim(24, 10) plt.sca(ax) # end of dark sky handles = [] for f in filterlist: plt.plot(system[f].wavelen, system[f].sb, color=filtercolors[f], linewidth=2) myline = mlines.Line2D([], [], color=filtercolors[f], linestyle='-', linewidth=2, label = '%s: m5 %.1f (sky %.1f)' %(f, m5[f], skyMag[f])) handles.append(myline) plt.plot(atmos.wavelen, atmos.sb, 'k:', label='Atmosphere, X=1.2') # Add legend for dark sky. myline = mlines.Line2D([], [], color='k', linestyle='-', label='Dark sky AB mags') handles.append(myline) # end of dark sky legend line plt.legend(loc=(0.01, 0.69), handles=handles, fancybox=True, numpoints=1, fontsize='small') plt.ylim(0, 1) plt.xlim(300, 1100) plt.xlabel('Wavelength (nm)') plt.ylabel('Fractional Throughput Response') if title == 'Vendor combo': title = '' plt.title('System total response curves %s' %(title)) if title == '': plt.savefig('throughputs.pdf', format='pdf', dpi=600) return m5
def calcM5(hardware, system, atmos, title='m5'): """ Calculate m5 values for all filters in hardware and system. Prints all values that go into "table 2" of the overview paper. Returns dictionary of m5 values. """ # photParams stores default values for the exposure time, nexp, size of the primary, # readnoise, gain, platescale, etc. # See https://github.com/lsst/sims_photUtils/blob/master/python/lsst/sims/photUtils/PhotometricParameters.py photParams = PhotometricParameters(gain=1) photParams_infinity = PhotometricParameters(readnoise=0, darkcurrent=0, othernoise=0, gain=1) # lsstDefaults stores default values for the FWHMeff. # See https://github.com/lsst/sims_photUtils/blob/master/python/lsst/sims/photUtils/LSSTdefaults.py lsstDefaults = LSSTdefaults() darksky = Sed() darksky.readSED_flambda(os.path.join('../siteProperties', 'darksky.dat')) flatSed = Sed() flatSed.setFlatSED() m5 = {} Tb = {} Sb = {} kAtm = {} Cm = {} dCm_infinity = {} sourceCounts = {} skyCounts = {} skyMag = {} gamma = {} for f in system: m5[f] = SignalToNoise.calcM5(darksky, system[f], hardware[f], photParams, FWHMeff=lsstDefaults.FWHMeff(f)) fNorm = flatSed.calcFluxNorm(m5[f], system[f]) flatSed.multiplyFluxNorm(fNorm) sourceCounts[f] = flatSed.calcADU(system[f], photParams=photParams) # Calculate the Skycounts expected in this bandpass. skyCounts[f] = (darksky.calcADU(hardware[f], photParams=photParams) * photParams.platescale**2) # Calculate the sky surface brightness. skyMag[f] = darksky.calcMag(hardware[f]) # Calculate the gamma value. gamma[f] = SignalToNoise.calcGamma(system[f], m5[f], photParams) # Calculate the "Throughput Integral" (this is the hardware + atmosphere) dwavelen = np.mean(np.diff(system[f].wavelen)) Tb[f] = np.sum(system[f].sb / system[f].wavelen) * dwavelen # Calculate the "Sigma" 'system integral' (this is the hardware only) Sb[f] = np.sum(hardware[f].sb / hardware[f].wavelen) * dwavelen # Calculate km - atmospheric extinction in a particular bandpass kAtm[f] = -2.5*np.log10(Tb[f] / Sb[f]) # Calculate the Cm and Cm_Infinity values. # m5 = Cm + 0.5*(msky - 21) + 2.5log10(0.7/FWHMeff) + 1.25log10(t/30) - km(X-1.0) # Exptime should be 30 seconds and X=1.0 exptime = photParams.exptime * photParams.nexp if exptime != 30.0: print "Whoa, exposure time was not as expected - got %s not 30 seconds. Please edit Cm calculation." %(exptime) # Assumes atmosphere used in system throughput is X=1.0 X = 1.0 Cm[f] = (m5[f] - 0.5*(skyMag[f] - 21) - 2.5*np.log10(0.7/lsstDefaults.FWHMeff(f))) # Calculate Cm_Infinity by setting readout noise to zero. m5inf = SignalToNoise.calcM5(darksky, system[f], hardware[f], photParams_infinity, FWHMeff=lsstDefaults.FWHMeff(f)) Cm_infinity = (m5inf - 0.5*(skyMag[f] - 21) - 2.5*np.log10(0.7/lsstDefaults.FWHMeff(f))) dCm_infinity[f] = Cm_infinity - Cm[f] print title print 'Filter FWHMeff FWHMgeom SkyMag SkyCounts Tb Sb kAtm Gamma Cm dCm_infinity m5 SourceCounts' for f in ('u', 'g' ,'r', 'i', 'z', 'y'): print '%s %.2f %.2f %.2f %.1f %.3f %.3f %.4f %.6f %.2f %.2f %.2f %.2f'\ %(f, lsstDefaults.FWHMeff(f), SignalToNoise.FWHMeff2FWHMgeom(lsstDefaults.FWHMeff(f)), skyMag[f], skyCounts[f], Tb[f], Sb[f], kAtm[f], gamma[f], Cm[f], dCm_infinity[f], m5[f], sourceCounts[f]) # Show what these look like individually (add sky & m5 limits on throughput curves) plt.figure() for f in filterlist: plt.plot(system[f].wavelen, system[f].sb, color=filtercolors[f], linewidth=2, label=f) plt.plot(atmosphere.wavelen, atmosphere.sb, 'k:', label='X=1.0') plt.legend(loc='center right', fontsize='smaller') plt.xlim(300, 1100) plt.ylim(0, 1) plt.xlabel('Wavelength (nm)') plt.ylabel('Throughput') plt.title('System Throughputs') plt.grid(True) plt.figure() ax = plt.gca() # Add dark sky ax2 = ax.twinx() plt.sca(ax2) skyab = -2.5*np.log10(darksky.fnu) - darksky.zp ax2.plot(darksky.wavelen, skyab, 'k-', linewidth=0.8, label='Dark sky mags') ax2.set_ylabel('AB mags') ax2.set_ylim(24, 14) plt.sca(ax) # end of dark sky handles = [] for f in filterlist: plt.plot(system[f].wavelen, system[f].sb, color=filtercolors[f], linewidth=2) myline = mlines.Line2D([], [], color=filtercolors[f], linestyle='-', linewidth=2, label = '%s: m5 %.1f (sky %.1f)' %(f, m5[f], skyMag[f])) handles.append(myline) plt.plot(atmos.wavelen, atmos.sb, 'k:', label='Atmosphere, X=1.0') # Add legend for dark sky. myline = mlines.Line2D([], [], color='k', linestyle='-', label='Dark sky AB mags/arcsec^2') handles.append(myline) # end of dark sky legend line plt.legend(loc=(0.01, 0.69), handles=handles, fancybox=True, numpoints=1, fontsize='small') plt.ylim(0, 1) plt.xlim(300, 1100) plt.xlabel('Wavelength (nm)') plt.ylabel('Fractional Throughput Response') plt.title('System total response curves %s' %(title)) return m5
def loadSedsFromList(self, sedNameList, magNormList, \ internalAvList=None, galacticAvList=None, redshiftList=None): """ Load the Seds specified by sedNameList, applying the specified normalization, extinction, and redshift. @param [in] sedList is a list of file names containing Seds @param [in] magNorm is the magnitude normalization @param [in] internalAvList is an optional list of A(V) due to internal dust @param [in] galacticAvList is an optional list of A(V) due to Milky Way dust @param [in] redshiftList is an optional list of redshifts for the input Sed Seds are read in and stored to this object's internal list of Seds. Note: if you constructed this SedList object without internalAvList, you cannot load Seds with internalAvList now. Likewise for galacticAvlist and redshiftList. """ if not self._initialized: if internalAvList is not None: self._internal_av_list = copy.deepcopy(list(internalAvList)) else: self._internal_av_list = None if galacticAvList is not None: self._galactic_av_list = copy.deepcopy(list(galacticAvList)) else: self._galactic_av_list = None if redshiftList is not None: self._redshift_list = copy.deepcopy(list(redshiftList)) else: self._redshift_list = None else: if self._internal_av_list is None and internalAvList is not None: raise RuntimeError("This SedList does not contain internalAvList") elif self._internal_av_list is not None: if internalAvList is None: self._internal_av_list += [None] * len(sedNameList) else: self._internal_av_list += list(internalAvList) if self._galactic_av_list is None and galacticAvList is not None: raise RuntimeError("This SedList does not contain galacticAvList") elif self._galactic_av_list is not None: if galacticAvList is None: self._galactic_av_list += [None] * len(sedNameList) else: self._galactic_av_list += list(galacticAvList) if self._redshift_list is None and redshiftList is not None: raise RuntimeError("This SedList does not contain redshiftList") elif self._redshift_list is not None: if redshiftList is None: self._redshift_list += [None] * len(sedNameList) else: self._redshift_list += list(redshiftList) for sedName in sedNameList: if sedName not in self._unique_sed_dict: sed = Sed() if self._spec_map is not None: sed.readSED_flambda(os.path.join(self._file_dir, self._spec_map[sedName])) else: sed.readSED_flambda(os.path.join(self._file_dir, sedName)) self._unique_sed_dict[sedName]=sed #now that we have loaded and copied all of the necessary SEDs, #we can apply magNorms temp_sed_list = [] for sedName, magNorm in zip(sedNameList, magNormList): ss = self._unique_sed_dict[sedName] sed=Sed(wavelen=ss.wavelen,flambda=ss.flambda,fnu=ss.fnu, name=ss.name) if sedName != "None": fNorm = sed.calcFluxNorm(magNorm, self._normalizing_bandpass) sed.multiplyFluxNorm(fNorm) temp_sed_list.append(sed) if internalAvList is not None: self._av_int_wavelen, \ self._a_int, \ self._b_int = self.applyAv(temp_sed_list, internalAvList, self._av_int_wavelen, self._a_int, self._b_int) if redshiftList is not None: self.applyRedshift(temp_sed_list, redshiftList) if self._wavelen_match is not None: for sedObj in temp_sed_list: if sedObj.wavelen is not None: sedObj.resampleSED(wavelen_match=self._wavelen_match) if galacticAvList is not None: self._av_gal_wavelen, \ self._a_gal, \ self._b_gal = self.applyAv(temp_sed_list, galacticAvList, self._av_gal_wavelen, self._a_gal, self._b_gal) self._sed_list += temp_sed_list self._initialized = True