def test_SED_sub(): """Check that SEDs subtract like I think they should... """ for z in [0, 0.2, 0.4]: a = galsim.SED(galsim.LookupTable([1,2,3,4,5], [1.1,2.2,3.3,4.4,5.5]), wave_type='nm', flux_type='fphotons') b = galsim.SED(galsim.LookupTable([1.1,2.2,3.0,4.4,5.5], [1.11,2.22,3.33,4.44,5.55]), wave_type='nm', flux_type='fphotons') if z != 0: a = a.atRedshift(z) b = b.atRedshift(z) c = a-b np.testing.assert_almost_equal(c.blue_limit, np.max([a.blue_limit, b.blue_limit]), 10, err_msg="Found wrong blue limit in SED.__sub__") np.testing.assert_almost_equal(c.red_limit, np.min([a.red_limit, b.red_limit]), 10, err_msg="Found wrong red limit in SED.__sub__") np.testing.assert_almost_equal(c(c.blue_limit), a(c.blue_limit) - b(c.blue_limit), 10, err_msg="Wrong difference in SED.__sub__") np.testing.assert_almost_equal(c(c.red_limit), a(c.red_limit) - b(c.red_limit), 10, err_msg="Wrong difference in SED.__sub__") x = 0.5 * (c.blue_limit + c.red_limit) np.testing.assert_almost_equal(c(x), a(x) - b(x), 10, err_msg="Wrong difference in SED.__sub__") np.testing.assert_almost_equal(c.redshift, a.redshift, 10, err_msg="Wrong redshift in SED difference") try: # Subracting two SEDs with different redshifts should fail. d = b.atRedshift(0.1) np.testing.assert_raises(ValueError, b.__sub__, d) except ImportError: print('The assert_raises tests require nose')
def test_SED_calculateSeeingMomentRatio(): # compute a relative moment shift and compare to externally generated known result. sed = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), 'nm', 'flambda') bandpass = galsim.Bandpass(os.path.join(bppath, 'LSST_r.dat'), 'nm') relative_size = sed.calculateSeeingMomentRatio(bandpass) # and now do the integral right here to compare. # \Delta r^2/r^2 = \frac{\int{sed(\lambda) * bandpass(\lambda) * (\lambda/500)^-0.4 d\lambda}} # {\int{sed(\lambda) * bandpass(\lambda) d\lambda}} waves = np.union1d(sed.wave_list, bandpass.wave_list) num = np.trapz(sed(waves) * bandpass(waves) * (waves/500.0)**(-0.4), waves) den = np.trapz(sed(waves) * bandpass(waves), waves) np.testing.assert_almost_equal(relative_size, num/den, 5) # Repeat with a function bandpass, since different path in code bp2 = galsim.Bandpass('1', 'nm', blue_limit=bandpass.blue_limit, red_limit=bandpass.red_limit) relative_size = sed.calculateSeeingMomentRatio(bp2) waves = (sed*bp2).wave_list num = np.trapz(sed(waves) * (waves/500.0)**(-0.4), waves) den = np.trapz(sed(waves), waves) np.testing.assert_almost_equal(relative_size, num/den, 4) # Invalid for dimensionless SED flat = galsim.SED(2.0, 'nm', '1') with assert_raises(galsim.GalSimSEDError): flat.calculateSeeingMomentRatio(bandpass)
def test_SED_div(): """Check that SEDs divide like I think they should... """ a0 = galsim.SED(galsim.LookupTable([1,2,3,4,5], [1.1,2.2,3.3,4.4,5.5]), wave_type='nm', flux_type='fphotons') for z in [0, 0.2, 0.4]: a = a0.atRedshift(z) # SED divided by function b = lambda w: w**2 c = a/b x = 3.0 np.testing.assert_almost_equal(c(x), a(x)/b(x), 10, err_msg="Found wrong value in SED.__div__") # SED divided by scalar d = a/4.2 np.testing.assert_almost_equal(d(x), a(x)/4.2, 10, err_msg="Found wrong value in SED.__div__") do_pickle(d) # assignment division d /= 2 np.testing.assert_almost_equal(d(x), a(x)/4.2/2, 10, err_msg="Found wrong value in SED.__div__") do_pickle(d) # SED divided by dimensionless SED e = galsim.SED('wave', 'nm', '1') d /= e np.testing.assert_almost_equal(d(x), a(x)/4.2/2/e(x), 10, err_msg="Found wrong value in SED.__div__")
def get_template_seds(Args): """ Return bulge, disk and composite SEDs at given redshift. The bulge and disk SEDs are normalized to 1.0 at 550 nm in rest-frame and then redshifted. Composite SED is the flux weighted sum of bulge and disk SEDs. Note: Total flux of SEDs are not normalized. @param Args Class with the following attributes: Args.disk_SED_name One of ['Sbc', 'Scd', 'Im', 'E'] to indicate disk SED.(default: 'Im') Args.bulge_SED_name One of ['Sbc', 'Scd', 'Im', 'E'] to indicate bulge SED.(default:'E') Args.redshift Redshift of galaxy (both bulge and disk). Args.bulge_frac Fraction of flux in bulge at 550 nm rest-frame. @returns bulge SED, disk SED, composite SED. """ path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/') b_SED = galsim.SED(path + "CWW_{}_ext.sed".format(Args.bulge_SED_name), wave_type='Ang', flux_type='flambda').thin(rel_err=1e-4) d_SED = galsim.SED(path + "CWW_{}_ext.sed".format(Args.disk_SED_name), wave_type='Ang', flux_type='flambda').thin(rel_err=1e-4) b_SED = b_SED.withFluxDensity(1.0, 550.0).atRedshift(Args.redshift) d_SED = d_SED.withFluxDensity(1.0, 550.0).atRedshift(Args.redshift) c_SED = b_SED * Args.bulge_frac + d_SED * (1. - Args.bulge_frac) return b_SED, d_SED, c_SED
def test_fnu_vs_flambda(): import time t1 = time.time() c = 2.99792458e17 # speed of light in nm/s h = 6.62606957e-27 # Planck's constant in erg seconds k = 1.3806488e-16 # Boltzmann's constant ergs per Kelvin nm_in_cm = 1e7 # read these straight from Wikipedia def rayleigh_jeans_fnu(T, w): nu = c / w return 2 * nu**2 * k * T / c**2 * nm_in_cm**2 # should have units of erg/s/cm^2/Hz def rayleigh_jeans_flambda(T, w): return 2 * c * k * T / w**4 * nm_in_cm**2 # should have units of erg/s/cm^2/nm waves = np.linspace(500, 1000, 100) fnu = rayleigh_jeans_fnu(5800, waves) flambda = rayleigh_jeans_flambda(5800, waves) for z in [0, 0.2, 0.4]: sed1 = galsim.SED(galsim.LookupTable(waves, fnu), flux_type='fnu') sed2 = galsim.SED(galsim.LookupTable(waves, flambda), flux_type='flambda') if z != 0: sed1 = sed1.atRedshift(z) sed2 = sed2.atRedshift(z) zwaves = waves * (1.0 + z) np.testing.assert_array_almost_equal( sed1(zwaves) / sed2(zwaves), np.ones(len(zwaves)), 10, err_msg="Check fnu & flambda consistency.") # Now also check that wavelengths in Angstroms work. waves_ang = waves * 10 sed3 = galsim.SED(galsim.LookupTable(waves_ang, fnu), flux_type='fnu', wave_type='Ang') sed4 = galsim.SED(galsim.LookupTable(waves_ang, flambda), flux_type='flambda', wave_type='Ang') if z != 0: sed3 = sed3.atRedshift(z) sed4 = sed4.atRedshift(z) np.testing.assert_array_almost_equal( sed1(zwaves) / sed3(zwaves), np.ones(len(zwaves)), 10, err_msg="Check nm and Ang SED wavelengths consistency.") np.testing.assert_array_almost_equal( sed2(zwaves) / sed4(zwaves), np.ones(len(zwaves)), 10, err_msg="Check nm and Ang SED wavelengths consistency.") t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
def withZeropoint(self, zeropoint): """ Assign a zeropoint to this Bandpass. A bandpass zeropoint is a float used to convert flux (in photons/s/cm^2) to magnitudes: mag = -2.5*log10(flux) + zeropoint Note that the zeropoint attribute does not propagate if you get a new Bandpass by multiplying or dividing an old Bandpass. The `zeropoint` argument can take a variety of possible forms: 1. a number, which will be the zeropoint 2. a galsim.SED. In this case, the zeropoint is set such that the magnitude of the supplied SED through the bandpass is 0.0 3. the string 'AB'. In this case, use an AB zeropoint. 4. the string 'Vega'. Use a Vega zeropoint. 5. the string 'ST'. Use a HST STmag zeropoint. @param zeropoint see above for valid input options @returns new Bandpass with zeropoint set. """ # Convert `zeropoint` from str to galsim.SED. if isinstance(zeropoint, str): if zeropoint.upper() == 'AB': AB_source = 3631e-23 # 3631 Jy in units of erg/s/Hz/cm^2 sed = galsim.SED(lambda wave: AB_source, wave_type='nm', flux_type='fnu') elif zeropoint.upper() == 'ST': # Use HST STmags: http://www.stsci.edu/hst/acs/analysis/zeropoints ST_flambda = 3.63e-8 # erg/s/cm^2/nm sed = galsim.SED(lambda wave: ST_flambda, wave_type='nm', flux_type='flambda') elif zeropoint.upper() == 'VEGA': # Use vega spectrum for SED import os vegafile = os.path.join(galsim.meta_data.share_dir, "SEDs", "vega.txt") sed = galsim.SED(vegafile, wave_type='nm', flux_type='flambda') else: raise ValueError( "Do not recognize Zeropoint string {0}.".format(zeropoint)) zeropoint = sed # Convert `zeropoint` from galsim.SED to float if isinstance(zeropoint, galsim.SED): flux = zeropoint.calculateFlux(self) zeropoint = 2.5 * np.log10(flux) # Should be a float now (or maybe an int). If not, raise an exception. if not isinstance(zeropoint, (float, int)): raise TypeError( "Don't know how to handle zeropoint of type: {0}".format( type(zeropoint))) return Bandpass(self._orig_tp, self.wave_type, self.blue_limit, self.red_limit, zeropoint, self.wave_list, self._tp)
def test_SED_add(): """Check that SEDs add like I think they should... """ import time t1 = time.time() for z in [0, 0.2, 0.4]: a = galsim.SED(galsim.LookupTable([1, 2, 3, 4, 5], [1.1, 2.2, 3.3, 4.4, 5.5]), flux_type='fphotons') b = galsim.SED(galsim.LookupTable([1.1, 2.2, 3.0, 4.4, 5.5], [1.11, 2.22, 3.33, 4.44, 5.55]), flux_type='fphotons') if z != 0: a = a.atRedshift(z) b = b.atRedshift(z) c = a + b np.testing.assert_almost_equal( c.blue_limit, np.max([a.blue_limit, b.blue_limit]), 10, err_msg="Found wrong blue limit in SED.__add__") np.testing.assert_almost_equal( c.red_limit, np.min([a.red_limit, b.red_limit]), 10, err_msg="Found wrong red limit in SED.__add__") np.testing.assert_almost_equal(c(c.blue_limit), a(c.blue_limit) + b(c.blue_limit), 10, err_msg="Wrong sum in SED.__add__") np.testing.assert_almost_equal(c(c.red_limit), a(c.red_limit) + b(c.red_limit), 10, err_msg="Wrong sum in SED.__add__") x = 0.5 * (c.blue_limit + c.red_limit) np.testing.assert_almost_equal(c(x), a(x) + b(x), 10, err_msg="Wrong sum in SED.__add__") np.testing.assert_almost_equal(c.redshift, a.redshift, 10, err_msg="Wrong redshift in SED sum") try: # Adding together two SEDs with different redshifts should fail. d = b.atRedshift(0.1) np.testing.assert_raises(ValueError, b.__add__, d) except ImportError: print 'The assert_raises tests require nose' t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
def test_SED_withFlux(): """ Check that setting the flux works. """ rband = galsim.Bandpass(os.path.join(bppath, 'LSST_r.dat'), 'nm') for z in [0, 0.2, 0.4]: for fast in [True, False]: a = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), wave_type='ang', flux_type='flambda', fast=fast) if z != 0: a = a.atRedshift(z) a = a.withFlux(1.0, rband) np.testing.assert_array_almost_equal(a.calculateFlux(rband), 1.0, 5, "Setting SED flux failed.") # Should be equivalent to multiplying an SED * Bandpass and computing the # "bolometric" flux. ab = a * rband bolo_bp = galsim.Bandpass('1', blue_limit=ab.blue_limit, red_limit=ab.red_limit, wave_type='nm') np.testing.assert_array_almost_equal( ab.calculateFlux(bolo_bp), 1.0, 5, "Calculating SED flux from sed * bp failed.")
def test_SED_atRedshift(): """Check that SEDs redshift correctly. """ a = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), wave_type='ang', flux_type='flambda') bolo_bp = galsim.Bandpass('1', blue_limit=a.blue_limit, red_limit=a.red_limit, wave_type='nm') bolo_flux = a.calculateFlux(bolo_bp) print('bolo_flux = ',bolo_flux) for z1, z2 in zip([-0.01, -0.02, 0.5, 1.0, 1.4], [-0.2, 0.2, 1.0, 1.0, 1.0]): b = a.atRedshift(z1) c = b.atRedshift(z1) # same redshift, so should be no change d = c.atRedshift(z2) # do a relative redshifting from z1 to z2 e = b.thin(rel_err=1.e-5) # effectively tests that wave_list is handled correctly. # (Issue #520) for w in [350, 500, 650]: print('a(w) = ',a(w)) print('b(w(1+z)) = ',b(w*(1.+z1))) print('c(w(1+z)) = ',c(w*(1.+z1))) print('d(w(1+z)) = ',d(w*(1.+z2))) print('e(w(1+z)) = ',e(w*(1.+z1))) np.testing.assert_almost_equal(a(w)/bolo_flux, b(w*(1.0+z1))/bolo_flux, 15, err_msg="error redshifting SED") np.testing.assert_almost_equal(a(w)/bolo_flux, c(w*(1.0+z1))/bolo_flux, 15, err_msg="error redshifting SED") np.testing.assert_almost_equal(a(w)/bolo_flux, d(w*(1.0+z2))/bolo_flux, 15, err_msg="error redshifting SED") np.testing.assert_almost_equal(a(w)/bolo_flux, e(w*(1.0+z1))/bolo_flux, 5, err_msg="error redshifting and thinning SED") with assert_raises(ValueError): a.atRedshift(-1.1)
def test_thin(): import time t1 = time.time() s = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), wave_type='ang', flux_type='flambda') bp = galsim.Bandpass('1', 'nm', blue_limit=s.blue_limit, red_limit=s.red_limit) flux = s.calculateFlux(bp) print "Original number of SED samples = ",len(s.wave_list) for err in [1.e-2, 1.e-3, 1.e-4, 1.e-5]: print "Test err = ",err thin_s = s.thin(rel_err=err, preserve_range=True, fast_search=False) thin_flux = thin_s.calculateFlux(bp) thin_err = (flux-thin_flux)/flux print "num samples with preserve_range = True, fast_search = False: ",len(thin_s.wave_list) print "realized error = ",(flux-thin_flux)/flux thin_s = s.thin(rel_err=err, preserve_range=True) thin_flux = thin_s.calculateFlux(bp) thin_err = (flux-thin_flux)/flux print "num samples with preserve_range = True: ",len(thin_s.wave_list) print "realized error = ",(flux-thin_flux)/flux assert np.abs(thin_err) < err, "Thinned SED failed accuracy goal, preserving range." thin_s = s.thin(rel_err=err, preserve_range=False) thin_flux = thin_s.calculateFlux(bp) thin_err = (flux-thin_flux)/flux print "num samples with preserve_range = False: ",len(thin_s.wave_list) print "realized error = ",(flux-thin_flux)/flux assert np.abs(thin_err) < err, "Thinned SED failed accuracy goal, w/ range shrinkage." t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2-t1)
def test_dep_chromatic(): """Test the deprecated methods in galsim/deprecated/chromatic.py """ import time t1 = time.time() g = galsim.Gaussian(sigma=0.34) sed = galsim.SED('wave**3') obj = g * sed band = galsim.Bandpass('1-((wave-700)/100)**2', blue_limit=600., red_limit=800.) im1 = check_dep(obj.draw, bandpass=band) im2 = obj.drawImage(band, method='no_pixel') np.testing.assert_almost_equal(im1.scale, im2.scale) np.testing.assert_equal(im1.bounds, im2.bounds) np.testing.assert_array_almost_equal(im1.array, im2.array) im1 = check_dep(obj.draw, bandpass=band, normalization='sb') im2 = obj.drawImage(band, method='sb') np.testing.assert_almost_equal(im1.scale, im2.scale) np.testing.assert_equal(im1.bounds, im2.bounds) np.testing.assert_array_almost_equal(im1.array, im2.array) t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def test_SED_div(): """Check that SEDs divide like I think they should... """ import time t1 = time.time() for z in [0, 0.2, 0.4]: a = galsim.SED(galsim.LookupTable([1,2,3,4,5], [1.1,2.2,3.3,4.4,5.5]), wave_type='nm', flux_type='fphotons') if z != 0: a = a.atRedshift(z) # SED divided by function b = lambda w: w**2 c = a/b x = 3.0 np.testing.assert_almost_equal(c(x), a(x)/b(x), 10, err_msg="Found wrong value in SED.__div__") # SED divided by scalar d = a/4.2 np.testing.assert_almost_equal(d(x), a(x)/4.2, 10, err_msg="Found wrong value in SED.__div__") do_pickle(d) # assignment division d /= 2 np.testing.assert_almost_equal(d(x), a(x)/4.2/2, 10, err_msg="Found wrong value in SED.__div__") do_pickle(d) t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def test_SED_atRedshift(): """Check that SEDs redshift correctly. """ import time t1 = time.time() a = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), wave_type='ang', flux_type='flambda') bolo_flux = a.calculateFlux(bandpass=None) for z1, z2 in zip([0.5, 1.0, 1.4], [1.0, 1.0, 1.0]): b = a.atRedshift(z1) c = b.atRedshift(z1) # same redshift, so should be no change d = c.atRedshift(z2) # do a relative redshifting from z1 to z2 e = b.thin(rel_err=1.e-5) # effectively tests that wave_list is handled correctly. # (Issue #520) for w in [350, 500, 650]: np.testing.assert_almost_equal(a(w), b(w*(1.0+z1)), 10, err_msg="error redshifting SED") np.testing.assert_almost_equal(a(w), c(w*(1.0+z1)), 10, err_msg="error redshifting SED") np.testing.assert_almost_equal(a(w), d(w*(1.0+z2)), 10, err_msg="error redshifting SED") np.testing.assert_almost_equal((a(w)-e(w*(1.0+z1)))/bolo_flux, 0., 5, err_msg="error redshifting and thinning SED") t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def test_combine_wave_list(): class A(object): def __init__(self, wave_list): self.wave_list = wave_list if self.wave_list: self.blue_limit = np.min(self.wave_list) self.red_limit = np.max(self.wave_list) a = A([1, 3, 5]) b = A([2, 4, 6]) c = A([2, 3, 4, 5]) d = A([7, 8, 9]) for a1, a2 in zip([a, a, b], [b, c, c]): wave_list, blue_limit, red_limit = ( galsim.utilities.combine_wave_list(a1, a2)) np.testing.assert_equal(wave_list, c.wave_list) np.testing.assert_equal(blue_limit, c.blue_limit) np.testing.assert_equal(red_limit, c.red_limit) with assert_raises(galsim.GalSimError): galsim.utilities.combine_wave_list(a, d) # Degenerate case works. sed = galsim.SED('CWW_Scd_ext.sed', wave_type='nm', flux_type='flambda') wave_list, blue_limit, red_limit = galsim.utilities.combine_wave_list(sed) np.testing.assert_equal(wave_list, sed.wave_list) np.testing.assert_equal(blue_limit, sed.blue_limit) np.testing.assert_equal(red_limit, sed.red_limit) # Doesn't know about our A class though. assert_raises(TypeError, galsim.utilities.combine_wave_list, a)
def test_ne(): """ Check that inequality works as expected.""" tput = lambda x: x / 1000 lt = galsim.LookupTable([400, 550], [0.4, 0.55], interpolant='linear') sed = galsim.SED('3', 'nm', 'flambda') # These should all compare unequal. bps = [ galsim.Bandpass(throughput=tput, wave_type='nm', blue_limit=400, red_limit=550), galsim.Bandpass(throughput=tput, wave_type='nm', blue_limit=400, red_limit=551), galsim.Bandpass(throughput=tput, wave_type='nm', blue_limit=401, red_limit=550), galsim.Bandpass(throughput=lt, wave_type='nm'), galsim.Bandpass(throughput=lt, wave_type='A'), galsim.Bandpass(throughput=lt, wave_type='nm', zeropoint=10.0), galsim.Bandpass(throughput=lt, wave_type='nm').withZeropoint('AB'), galsim.Bandpass(throughput=lt, wave_type='nm').withZeropoint('ST'), galsim.Bandpass(throughput=lt, wave_type='nm').withZeropoint('Vega'), galsim.Bandpass(throughput=lt, wave_type='nm').withZeropoint(100.0), galsim.Bandpass(throughput=lt, wave_type='nm').withZeropoint(sed) ] all_obj_diff(bps)
def test_thin(): """Test that bandpass thinning works with the requested accuracy.""" s = galsim.SED('1', wave_type='nm', flux_type='fphotons') bp = galsim.Bandpass(os.path.join(datapath, 'LSST_r.dat'), 'nm') flux = s.calculateFlux(bp) print("Original number of bandpass samples = ", len(bp.wave_list)) for err in [1.e-2, 1.e-3, 1.e-4, 1.e-5]: print("Test err = ", err) thin_bp = bp.thin(rel_err=err, preserve_range=True, fast_search=False) thin_flux = s.calculateFlux(thin_bp) thin_err = (flux - thin_flux) / flux print("num samples with preserve_range = True, fast_search = False: ", len(thin_bp.wave_list)) print("realized error = ", (flux - thin_flux) / flux) thin_bp = bp.thin(rel_err=err, preserve_range=True) thin_flux = s.calculateFlux(thin_bp) thin_err = (flux - thin_flux) / flux print("num samples with preserve_range = True: ", len(thin_bp.wave_list)) print("realized error = ", (flux - thin_flux) / flux) assert np.abs( thin_err ) < err, "Thinned bandpass failed accuracy goal, preserving range." thin_bp = bp.thin(rel_err=err, preserve_range=False) thin_flux = s.calculateFlux(thin_bp) thin_err = (flux - thin_flux) / flux print("num samples with preserve_range = False: ", len(thin_bp.wave_list)) print("realized error = ", (flux - thin_flux) / flux) assert np.abs( thin_err ) < err, "Thinned bandpass failed accuracy goal, w/ range shrinkage."
def test_SED_calculateDCRMomentShifts(): import time t1 = time.time() # compute some moment shifts sed = galsim.SED(os.path.join(datapath, 'CWW_E_ext.sed')) bandpass = galsim.Bandpass(os.path.join(datapath, 'LSST_r.dat')) Rbar, V = sed.calculateDCRMomentShifts(bandpass, zenith_angle=45 * galsim.degrees) # now rotate parallactic angle 180 degrees, and see if the output makes sense. Rbar2, V2 = sed.calculateDCRMomentShifts(bandpass, zenith_angle=45 * galsim.degrees, parallactic_angle=180 * galsim.degrees) np.testing.assert_array_almost_equal(Rbar, -Rbar2, 15) np.testing.assert_array_almost_equal(V, V2, 25) # now rotate parallactic angle 90 degrees. Rbar3, V3 = sed.calculateDCRMomentShifts(bandpass, zenith_angle=45 * galsim.degrees, parallactic_angle=90 * galsim.degrees) np.testing.assert_almost_equal(Rbar[0], Rbar3[1], 15) np.testing.assert_almost_equal(V[1, 1], V3[0, 0], 25) # and now test against an external known result. np.testing.assert_almost_equal(V[1, 1] * (180.0 / np.pi * 3600)**2, 0.0065, 4) t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
def test_SED_calculateDCRMomentShifts(): # compute some moment shifts sed = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), 'nm', 'flambda') bandpass = galsim.Bandpass(os.path.join(bppath, 'LSST_r.dat'), 'nm') Rbar, V = sed.calculateDCRMomentShifts(bandpass, zenith_angle=45*galsim.degrees) # now rotate parallactic angle 180 degrees, and see if the output makes sense. Rbar2, V2 = sed.calculateDCRMomentShifts(bandpass, zenith_angle=45*galsim.degrees, parallactic_angle=180*galsim.degrees) np.testing.assert_array_almost_equal(Rbar, -Rbar2, 15) np.testing.assert_array_almost_equal(V, V2, 25) # now rotate parallactic angle 90 degrees. Rbar3, V3 = sed.calculateDCRMomentShifts(bandpass, zenith_angle=45*galsim.degrees, parallactic_angle=90*galsim.degrees) np.testing.assert_almost_equal(Rbar[0], Rbar3[1], 15) np.testing.assert_almost_equal(V[1,1], V3[0,0], 25) # and now do the integral right here to compare. # \bar{R} = \frac{\int{sed(\lambda) * bandpass(\lambda) * R(\lambda) d\lambda}} # {\int{sed(\lambda) * bandpass(\lambda) d\lambda}} # where sed is in units of photons/nm (which is the default) waves = np.union1d(sed.wave_list, bandpass.wave_list) R = galsim.dcr.get_refraction(waves, 45.*galsim.degrees) Rnum = np.trapz(sed(waves) * bandpass(waves) * R, waves) den = np.trapz(sed(waves) * bandpass(waves), waves) rad2arcsec = galsim.radians / galsim.arcsec np.testing.assert_almost_equal(Rnum/den*rad2arcsec, Rbar[1]*rad2arcsec, 4) # and for the second moment, V, the numerator is: # \int{sed(\lambda) * bandpass(\lambda) * (R(\lambda) - Rbar)^2 d\lambda} Vnum = np.trapz(sed(waves) * bandpass(waves) * (R - Rnum/den)**2, waves) np.testing.assert_almost_equal(Vnum/den, V[1,1], 5)
def flux_model(self): tot_mag = np.random.choice(self.cat) sed = galsim.SED('CWW_E_ext.sed', 'A', 'flambda') sed = sed.withMagnitude(tot_mag, self.bpass) #flux = sed.calculateFlux(self.bpass) return sed
def get_stellar_seds(pickles_path, spec_types, target_flux_density=1.0, wavelength=500, show=False): """Create templates for stellar sources """ pickles_idx = ApTable.read(os.path.join(pickles_path, "pickles_uk.fits")) pickles_spt = [spt.rstrip() for spt in pickles_idx["SPTYPE"]] seds_stellar = [] for spt in spec_types: filename = os.path.join( pickles_path, pickles_idx[pickles_spt.index(spt)]["FILENAME"].rstrip() + ".fits") data = fits.open(filename)[1].data tbl = galsim.LookupTable(data["wavelength"], data["flux"]) sed = galsim.SED(tbl, wave_type="a", flux_type="flambda") seds_stellar.append( sed.withFluxDensity(target_flux_density=target_flux_density, wavelength=wavelength)) if show: for s, spt in enumerate(spec_types): tmp = seds_stellar[s] plt.plot(tmp._spec.x, tmp._spec.f / np.sum(tmp._spec.f), label=spt) plt.title("Stellar Spectra") plt.xlabel("Wavelength") plt.ylabel("Normalized Flux") plt.legend() plt.show() return seds_stellar
def test_SED_mul(): """Check that SEDs multiply like I think they should... """ for z in [0, 0.2, 0.4]: a = galsim.SED(galsim.LookupTable([1,2,3,4,5], [1.1,2.2,3.3,4.4,5.5]), wave_type='nm', flux_type='fphotons') if z != 0: a = a.atRedshift(z) # SED multiplied by function b = lambda w: w**2 c = a*b x = 3.0 np.testing.assert_almost_equal(c(x), a(x) * b(x), 10, err_msg="Found wrong value in SED.__mul__") # function multiplied by SED c = b*a np.testing.assert_almost_equal(c(x), a(x) * b(x), 10, err_msg="Found wrong value in SED.__rmul__") # SED multiplied by scalar d = a*4.2 np.testing.assert_almost_equal(d(x), a(x) * 4.2, 10, err_msg="Found wrong value in SED.__mul__") do_pickle(d) # assignment multiplication d *= 2 np.testing.assert_almost_equal(d(x), a(x) * 4.2 * 2, 10, err_msg="Found wrong value in SED.__mul__") do_pickle(d)
def test_dep_sed(): """Test the deprecated methods in galsim/deprecated/sed.py. """ z = 0.4 a = galsim.SED(galsim.LookupTable([1, 2, 3, 4, 5], [1.1, 2.2, 3.3, 4.4, 5.5]), wave_type='nm', flux_type='fphotons', redshift=0.4) b = lambda w: w**2 # function divided by SED #c = b/a c = check_dep(a.__rdiv__, b) x = 3.0 np.testing.assert_almost_equal(c(x), b(x) / a(x), 10, err_msg="Found wrong value in SED.__rdiv__") # number divided by SED #d = x/a d = check_dep(a.__rdiv__, x) np.testing.assert_almost_equal(d(x), x / a(x), 10, err_msg="Found wrong value in SED.__rdiv__")
def test_photon_io(): """Test the ability to read and write photons to a file """ nphotons = 1000 obj = galsim.Exponential(flux=1.7, scale_radius=2.3) rng = galsim.UniformDeviate(1234) image = obj.drawImage(method='phot', n_photons=nphotons, save_photons=True, rng=rng) photons = image.photons assert photons.size() == len(photons) == nphotons with assert_raises(galsim.GalSimIncompatibleValuesError): obj.drawImage(method='phot', n_photons=nphotons, save_photons=True, maxN=1.e5) file_name = 'output/photons1.dat' photons.write(file_name) photons1 = galsim.PhotonArray.read(file_name) assert photons1.size() == nphotons assert not photons1.hasAllocatedWavelengths() assert not photons1.hasAllocatedAngles() np.testing.assert_array_equal(photons1.x, photons.x) np.testing.assert_array_equal(photons1.y, photons.y) np.testing.assert_array_equal(photons1.flux, photons.flux) sed = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), 'nm', 'flambda').thin() bandpass = galsim.Bandpass(os.path.join(bppath, 'LSST_r.dat'), 'nm').thin() wave_sampler = galsim.WavelengthSampler(sed, bandpass, rng) angle_sampler = galsim.FRatioAngles(1.3, 0.3, rng) ops = [wave_sampler, angle_sampler] for op in ops: op.applyTo(photons) file_name = 'output/photons2.dat' photons.write(file_name) photons2 = galsim.PhotonArray.read(file_name) assert photons2.size() == nphotons assert photons2.hasAllocatedWavelengths() assert photons2.hasAllocatedAngles() np.testing.assert_array_equal(photons2.x, photons.x) np.testing.assert_array_equal(photons2.y, photons.y) np.testing.assert_array_equal(photons2.flux, photons.flux) np.testing.assert_array_equal(photons2.dxdz, photons.dxdz) np.testing.assert_array_equal(photons2.dydz, photons.dydz) np.testing.assert_array_equal(photons2.wavelength, photons.wavelength)
def test_SED_add(): """Check that SEDs add like I think they should... """ for z in [0, 0.2, 0.4]: a = galsim.SED(galsim.LookupTable([1,2,3,4,5], [1.1,2.2,3.3,4.4,5.5]), wave_type='nm', flux_type='fphotons') b = galsim.SED(galsim.LookupTable([1.1,2.2,3.0,4.4,5.5], [1.11,2.22,3.33,4.44,5.55]), wave_type='nm', flux_type='fphotons') if z != 0: a = a.atRedshift(z) b = b.atRedshift(z) c = a+b np.testing.assert_almost_equal(c.blue_limit, np.max([a.blue_limit, b.blue_limit]), 10, err_msg="Found wrong blue limit in SED.__add__") np.testing.assert_almost_equal(c.red_limit, np.min([a.red_limit, b.red_limit]), 10, err_msg="Found wrong red limit in SED.__add__") np.testing.assert_almost_equal(c(c.blue_limit), a(c.blue_limit) + b(c.blue_limit), 10, err_msg="Wrong sum in SED.__add__") np.testing.assert_almost_equal(c(c.red_limit), a(c.red_limit) + b(c.red_limit), 10, err_msg="Wrong sum in SED.__add__") x = 0.5 * (c.blue_limit + c.red_limit) np.testing.assert_almost_equal(c(x), a(x) + b(x), 10, err_msg="Wrong sum in SED.__add__") np.testing.assert_almost_equal(c.redshift, a.redshift, 10, err_msg="Wrong redshift in SED sum") # Adding together two SEDs with different redshifts should fail. d = b.atRedshift(0.1) with assert_raises(galsim.GalSimIncompatibleValuesError): b + d with assert_raises(galsim.GalSimIncompatibleValuesError): d + b # Can't add incompatible spectral types a = a.atRedshift(0) b = a.atRedshift(0) c = galsim.SED(2.0, 'nm', '1') with assert_raises(galsim.GalSimIncompatibleValuesError): a + c with assert_raises(galsim.GalSimIncompatibleValuesError): c + a with assert_raises(galsim.GalSimIncompatibleValuesError): b + c with assert_raises(galsim.GalSimIncompatibleValuesError): c + b
def test_thin(): s = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), wave_type='ang', flux_type='flambda', fast=False) bp = galsim.Bandpass('1', 'nm', blue_limit=s.blue_limit, red_limit=s.red_limit) flux = s.calculateFlux(bp) print("Original number of SED samples = ",len(s.wave_list)) for err in [1.e-2, 1.e-3, 1.e-4, 1.e-5]: print("Test err = ",err) thin_s = s.thin(rel_err=err, preserve_range=True, fast_search=False) thin_flux = thin_s.calculateFlux(bp) thin_err = (flux-thin_flux)/flux print("num samples with preserve_range = True, fast_search = False: ",len(thin_s.wave_list)) print("realized error = ",(flux-thin_flux)/flux) thin_s = s.thin(rel_err=err, preserve_range=True) thin_flux = thin_s.calculateFlux(bp) thin_err = (flux-thin_flux)/flux print("num samples with preserve_range = True: ",len(thin_s.wave_list)) print("realized error = ",(flux-thin_flux)/flux) assert np.abs(thin_err) < err, "Thinned SED failed accuracy goal, preserving range." thin_s = s.thin(rel_err=err, preserve_range=False) thin_flux = thin_s.calculateFlux(bp.truncate(thin_s.blue_limit, thin_s.red_limit)) thin_err = (flux-thin_flux)/flux print("num samples with preserve_range = False: ",len(thin_s.wave_list)) print("realized error = ",(flux-thin_flux)/flux) assert np.abs(thin_err) < err, "Thinned SED failed accuracy goal, w/ range shrinkage." assert_raises(ValueError, s.thin, rel_err=-0.5) assert_raises(ValueError, s.thin, rel_err=1.5) # These errors aren't accessible from the SED or Bandpass calls. assert_raises(ValueError, galsim.utilities.thin_tabulated_values, s.wave_list[3:], s._spec.getVals()) assert_raises(ValueError, galsim.utilities.thin_tabulated_values, s.wave_list[-1::-1], s._spec.getVals()) # Check some pathalogical spectra to stress the thinning algorithm s = galsim.SED(galsim.LookupTable(range(6), [0,0,1,1,0,0]),'nm','1').thin() print('s = ',s) np.testing.assert_equal(s.wave_list, range(1,5)) s = galsim.SED(galsim.LookupTable(range(6), [0,0,1,1,0,0]),'nm','1').thin(trim_zeros=False) print('s = ',s) np.testing.assert_equal(s.wave_list, range(6)) s = galsim.SED(galsim.LookupTable(range(8), [1.e-8,1.e-6,1,1,1,1.e-6,1.e-10,1.e-100]), 'nm','1').thin(preserve_range=False) print('s = ',s) np.testing.assert_equal(s.wave_list, range(1,6)) s = galsim.SED(galsim.LookupTable(range(8), np.zeros(8)),'nm','1').thin() print('s = ',s) np.testing.assert_equal(s.wave_list, [0,7]) s = galsim.SED(galsim.LookupTable(range(2), [1,1], interpolant='linear'),'nm','1').thin() print('s = ',s) np.testing.assert_equal(s.wave_list, [0,1]) s = galsim.SED(galsim.LookupTable(range(3), [1, 1.e-20, 0], interpolant='linear'), 'nm','1').thin(preserve_range=False) print('s = ',s) np.testing.assert_equal(s.wave_list, [0,1])
def _makeParametric(self, indices, chromatic, gsparams): if chromatic: # Defer making the Bandpass and reading in SEDs until we actually are going to use them. # It's not a huge calculation, but the thin() call especially isn't trivial. if self._bandpass is None: # We have to set an appropriate zeropoint. This is slightly complicated: The # nominal COSMOS zeropoint for single-orbit depth (2000s of usable exposure time, # across 4 dithered exposures) is supposedly 25.94. But the science images that we # are using were normalized to count rate, not counts, meaning that an object with # mag=25.94 has a count rate of 1 photon/sec, not 1 photon total. Since we've # declared our flux normalization for the outputs to be appropriate for a 1s # exposure, we use this zeropoint directly. zp = 25.94 self._bandpass = galsim.Bandpass( os.path.join(galsim.meta_data.share_dir, 'wfc_F814W.dat.gz'), wave_type='ang').thin().withZeropoint(zp) # This means that when drawing chromatic parametric galaxies, the outputs will be # properly normalized in terms of counts. # Read in some SEDs. self._sed = [ # bulge galsim.SED( os.path.join(galsim.meta_data.share_dir, 'CWW_E_ext.sed')), # disk galsim.SED( os.path.join(galsim.meta_data.share_dir, 'CWW_Scd_ext.sed')), # intermediate galsim.SED( os.path.join(galsim.meta_data.share_dir, 'CWW_Sbc_ext.sed')) ] gal_list = [] for index in indices: record = self.param_cat[self.orig_index[index]] gal = self._buildParametric(record, gsparams, chromatic, self._bandpass, self._sed) gal_list.append(gal) return gal_list
def test_SED_div(): """Check that SEDs divide like I think they should... """ a0_lt = galsim.SED(galsim.LookupTable([1,2,3,4,5], [1.1,2.2,3.3,4.4,5.5]), wave_type='nm', flux_type='fphotons') a0_fn = galsim.SED('wave', wave_type='nm', flux_type='fphotons') for z in [0, 0.2, 0.4]: for a0 in [a0_lt, a0_fn]: a = a0.atRedshift(z) # SED divided by function b = lambda w: w**2 c = a/b x = 3.0 np.testing.assert_almost_equal(c(x), a(x)/b(x), 10, err_msg="Found wrong value in SED.__div__") # SED divided by scalar d = a/4.2 np.testing.assert_almost_equal(d(x), a(x)/4.2, 10, err_msg="Found wrong value in SED.__div__") # assignment division d /= 2 np.testing.assert_almost_equal(d(x), a(x)/4.2/2, 10, err_msg="Found wrong value in SED.__div__") if a0 is a0_lt: do_pickle(d) # SED divided by dimensionless SED e = galsim.SED('wave', 'nm', '1') d /= e np.testing.assert_almost_equal(d(x), a(x)/4.2/2/e(x), 10, err_msg="Found wrong value in SED.__div__") # Can't divide by spectral SED with assert_raises(galsim.GalSimSEDError): a0_lt / a0_fn with assert_raises(galsim.GalSimSEDError): a0_fn / a0_lt with assert_raises(galsim.GalSimSEDError): e / a0_lt with assert_raises(galsim.GalSimSEDError): e / a0_fn
def test_SED_calculateMagnitude(): """ Check that magnitudes work as expected. """ # Test that we can create a zeropoint with an SED, and that magnitudes for that SED are # then 0.0 for z in [0, 0.2, 0.4]: sed = galsim.SED(spec='wave', wave_type='nm', flux_type='flambda') if z != 0: sed = sed.atRedshift(z) bandpass = galsim.Bandpass(galsim.LookupTable([1,2,3,4,5], [1,2,3,4,5]), 'nm').withZeropoint(sed) np.testing.assert_almost_equal(sed.calculateMagnitude(bandpass), 0.0) # Try multiplying SED by 100 to verify that magnitude decreases by 5 sed *= 100 np.testing.assert_almost_equal(sed.calculateMagnitude(bandpass), -5.0) # Try setting zeropoint to a constant. bandpass = galsim.Bandpass(galsim.LookupTable([1,2,3,4,5], [1,2,3,4,5]), 'nm').withZeropoint(6.0) np.testing.assert_almost_equal(sed.calculateMagnitude(bandpass), (sed*100).calculateMagnitude(bandpass)+5.0) # Try setting AB zeropoint bandpass = (galsim.Bandpass(galsim.LookupTable([1,2,3,4,5], [1,2,3,4,5]), 'nm') .withZeropoint('AB', effective_diameter=640.0, exptime=15.0)) np.testing.assert_almost_equal(sed.calculateMagnitude(bandpass), (sed*100).calculateMagnitude(bandpass)+5.0) # See if we can set a magnitude. sed = sed.withMagnitude(24.0, bandpass) np.testing.assert_almost_equal(sed.calculateMagnitude(bandpass), 24.0) # Test intended meaning of zeropoint. I.e., that an object with magnitude equal to the # zeropoint will have a flux of 1.0. bandpass = galsim.Bandpass(galsim.LookupTable([1,2,3,4,5], [1,2,3,4,5]), 'nm').withZeropoint(24.0) sed = sed.withMagnitude(bandpass.zeropoint, bandpass) np.testing.assert_almost_equal(sed.calculateFlux(bandpass), 1.0, 10) # See if Vega magnitudes work. # The following AB/Vega conversions are sourced from # http://www.astronomy.ohio-state.edu/~martini/usefuldata.html # Almost certainly, the LSST filters and the filters used on this website are not perfect # matches, but should give some idea of the expected conversion between Vega magnitudes and AB # magnitudes. The results are consistent to 0.1 magnitudes, which is encouraging, but the true # accuracy of the get/set magnitude algorithms is probably much better than this. ugrizy_vega_ab_conversions = [0.91, -0.08, 0.16, 0.37, 0.54, 0.634] filter_names = 'ugrizy' sed = sed.atRedshift(0.0) for conversion, filter_name in zip(ugrizy_vega_ab_conversions, filter_names): filter_filename = os.path.join(bppath, 'LSST_{0}.dat'.format(filter_name)) AB_bandpass = (galsim.Bandpass(filter_filename, 'nm') .withZeropoint('AB', effective_diameter=640, exptime=15)) vega_bandpass = (galsim.Bandpass(filter_filename, 'nm') .withZeropoint('vega', effective_diameter=640, exptime=15)) AB_mag = sed.calculateMagnitude(AB_bandpass) vega_mag = sed.calculateMagnitude(vega_bandpass) assert (abs((AB_mag - vega_mag) - conversion) < 0.1)
def test_SED_init(): """Check that certain invalid SED initializations are trapped. """ import time t1 = time.time() try: # These fail. np.testing.assert_raises(ValueError, galsim.SED, spec='blah') np.testing.assert_raises(ValueError, galsim.SED, spec='wave+') np.testing.assert_raises(ValueError, galsim.SED, spec='somewhere/a/file') np.testing.assert_raises(ValueError, galsim.SED, spec='/somewhere/a/file') np.testing.assert_raises(ValueError, galsim.SED, spec=lambda w: 1.0, wave_type='bar') np.testing.assert_raises(ValueError, galsim.SED, spec=lambda w: 1.0, flux_type='bar') except ImportError: print 'The assert_raises tests require nose' # These should succeed. galsim.SED(spec='wave') galsim.SED(spec='wave/wave') galsim.SED(spec=lambda w: 1.0) galsim.SED(spec='1./(wave-700)') # Also check for invalid calls foo = np.arange(10.) + 1. sed = galsim.SED(galsim.LookupTable(foo, foo)) try: np.testing.assert_raises(ValueError, sed, 0.5) np.testing.assert_raises(ValueError, sed, 12.0) except ImportError: print 'The assert_raises tests require nose' t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
def test_wavelength_sampler(): nphotons = 1000 obj = galsim.Exponential(flux=1.7, scale_radius=2.3) rng = galsim.UniformDeviate(1234) photon_array = obj.SBProfile.shoot(nphotons, rng) bppath = os.path.abspath(os.path.join(path, "../examples/data/")) sedpath = os.path.abspath(os.path.join(path, "../share/")) sed = galsim.SED(os.path.join(sedpath, 'CWW_E_ext.sed'), 'nm', 'flambda').thin() bandpass = galsim.Bandpass(os.path.join(bppath, 'LSST_r.dat'), 'nm').thin() sampler = galsim.WavelengthSampler(sed, bandpass, rng) sampler.applyTo(photon_array) # Note: the underlying functionality of the sampleWavelengths function is tested # in test_sed.py. So here we are really just testing that the wrapper class is # properly writing to the photon_array.wavelengths array. assert photon_array.hasAllocatedWavelengths() assert not photon_array.hasAllocatedAngles() print('mean wavelength = ',np.mean(photon_array.wavelength)) print('min wavelength = ',np.min(photon_array.wavelength)) print('max wavelength = ',np.max(photon_array.wavelength)) assert np.min(photon_array.wavelength) > bandpass.blue_limit assert np.max(photon_array.wavelength) < bandpass.red_limit # This is a regression test based on the value at commit 0b0cc764a9 np.testing.assert_almost_equal(np.mean(photon_array.wavelength), 616.92072, decimal=3) # Test that using this as a surface op work properly. # First do the shooting and clipping manually. im1 = galsim.Image(64,64,scale=1) im1.setCenter(0,0) photon_array.flux[photon_array.wavelength < 600] = 0. photon_array.addTo(im1.image.view()) # Make a dummy surface op that clips any photons with lambda < 600 class Clip600(object): def applyTo(self, photon_array): photon_array.flux[photon_array.wavelength < 600] = 0. # Use (a new) sampler and clip600 as surface_ops in drawImage im2 = galsim.Image(64,64,scale=1) im2.setCenter(0,0) clip600 = Clip600() rng2 = galsim.BaseDeviate(1234) sampler2 = galsim.WavelengthSampler(sed, bandpass, rng2) obj.drawImage(im2, method='phot', n_photons=nphotons, use_true_center=False, surface_ops=[sampler2,clip600], rng=rng2) print('sum = ',im1.array.sum(),im2.array.sum()) np.testing.assert_array_equal(im1.array, im2.array)