def lsst_flare_fluxes_from_u(ju_flux): """ Convert from Johnson U band flux to flux in the LSST bands by assuming the flare is a 9000K black body (see Section 4 of Hawley et al 2003, ApJ 597, 535) Parameters ---------- flux in Johnson U band (either a float or a numpy array) Returns ------- floats/numpy arrays of fluxes in all 6 LSST bands """ if not hasattr(lsst_flare_fluxes_from_u, 'johnson_u_raw_flux'): t_start = time.time() throughputs_dir = getPackageDir('throughputs') johnson_dir = os.path.join(throughputs_dir, 'johnson') johnson_u_hw = Bandpass() johnson_u_hw.readThroughput(os.path.join(johnson_dir, 'johnson_U.dat')) atm = Bandpass() atm.readThroughput( os.path.join(throughputs_dir, 'baseline', 'atmos_std.dat')) wv, sb = johnson_u_hw.multiplyThroughputs(atm.wavelen, atm.sb) johnson_u = Bandpass(wavelen=wv, sb=sb) boltzmann_k = 1.3807e-16 # erg/K planck_h = 6.6261e-27 # erg*s _c = 2.9979e10 # cm/s hc_over_k = 1.4387e7 # nm*K temp = 9000.0 # black body temperature in Kelvin bb_wavelen = np.arange(200.0, 1500.0, 0.1) # in nanometers exp_arg = hc_over_k / (temp * bb_wavelen) exp_term = 1.0 / (np.exp(exp_arg) - 1.0) ln_exp_term = np.log(exp_term) # the -7.0 np.log(10) will convert wavelen into centimeters log_bb_flambda = -5.0 * (np.log(bb_wavelen) - 7.0 * np.log(10.0)) + ln_exp_term log_bb_flambda += np.log(2.0) + np.log(planck_h) + 2.0 * np.log(_c) # assume these stars all have radii half that of the Sun; # see Boyajian et al. 2012 (ApJ 757, 112) r_sun = 6.957e10 # cm log_bb_flambda += np.log( 4.0 * np.pi * np.pi) + 2.0 * np.log(0.5 * r_sun) # thee -7.0*np.log(10.0) makes sure we get ergs/s/cm^2/nm bb_flambda = np.exp(log_bb_flambda - 7.0 * np.log(10)) bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) # because we have a flux in ergs/s but need a flux in # the normalized units of Sed.calcFlux (see eqn 2.1 # of the LSST Science Book), we will calculate the # ergs/s/cm^2 of a raw, unnormalized blackbody spectrum # in the Johnson U band, find the factor that converts # that raw flux into our specified flux, and then # multiply that factor *by the fluxes calculated for the # blackbody in the LSST filters using Sed.calcFlux()*. # This should give us the correct normalized flux for # the flares in the LSST filters. lsst_flare_fluxes_from_u.johnson_u_raw_flux = bb_sed.calcErgs( johnson_u) lsst_bands = BandpassDict.loadTotalBandpassesFromFiles() norm_raw = None lsst_flare_fluxes_from_u.lsst_raw_flux_dict = {} for band_name in ('u', 'g', 'r', 'i', 'z', 'y'): bp = lsst_bands[band_name] flux = bb_sed.calcFlux(bp) lsst_flare_fluxes_from_u.lsst_raw_flux_dict[band_name] = flux if norm_raw is None: norm_raw = flux print('raw flux in %s = %e; %e; %e' % (band_name, flux, flux / norm_raw, bb_sed.calcErgs(bp))) print('sed johnson flux %e' % lsst_flare_fluxes_from_u.johnson_u_raw_flux) print('that init took %e' % (time.time() - t_start)) factor = ju_flux / lsst_flare_fluxes_from_u.johnson_u_raw_flux u_flux_out = factor * lsst_flare_fluxes_from_u.lsst_raw_flux_dict['u'] g_flux_out = factor * lsst_flare_fluxes_from_u.lsst_raw_flux_dict['g'] r_flux_out = factor * lsst_flare_fluxes_from_u.lsst_raw_flux_dict['r'] i_flux_out = factor * lsst_flare_fluxes_from_u.lsst_raw_flux_dict['i'] z_flux_out = factor * lsst_flare_fluxes_from_u.lsst_raw_flux_dict['z'] y_flux_out = factor * lsst_flare_fluxes_from_u.lsst_raw_flux_dict['y'] return (u_flux_out, g_flux_out, r_flux_out, i_flux_out, z_flux_out, y_flux_out)
def test_calcErgs(self): """ Test that calcErgs actually calculates the flux of a source in ergs/s/cm^2 by running it on black bodies with flat bandpasses and comparing to the Stefan-Boltzmann law. """ boltzmann_k = 1.3807e-16 # in ergs/Kelvin planck_h = 6.6261e-27 # in cm^2*g/s speed_of_light = 2.9979e10 # in cm/s stefan_boltzmann_sigma = 5.6705e-5 # in ergs/cm^2/s/Kelvin wavelen_arr = np.arange(10.0, 200000.0, 10.0) # in nm bp = Bandpass(wavelen=wavelen_arr, sb=np.ones(len(wavelen_arr))) log10_bb_factor = np.log10(2.0) + np.log10(planck_h) log10_bb_factor += 2.0*np.log10(speed_of_light) log10_bb_factor -= 5.0*(np.log10(wavelen_arr) - 7.0) # convert wavelen to cm for temp in np.arange(5000.0, 7000.0, 250.0): log10_exp_arg = np.log10(planck_h) + np.log10(speed_of_light) log10_exp_arg -= (np.log10(wavelen_arr) - 7.0) log10_exp_arg -= (np.log10(boltzmann_k) + np.log10(temp)) exp_arg = np.power(10.0, log10_exp_arg) log10_bose_factor = -1.0*np.log10(np.exp(exp_arg)-1.0) # the -7.0 below is because, otherwise, flambda will be in # ergs/s/cm^2/cm and we want ergs/s/cm^2/nm # # the np.pi comes from the integral in the 'Stefan-Boltzmann' # section of # https://en.wikipedia.org/wiki/Planck%27s_law#Stefan.E2.80.93Boltzmann_law # bb_flambda = np.pi*np.power(10.0, log10_bb_factor+log10_bose_factor-7.0) sed = Sed(wavelen=wavelen_arr, flambda=bb_flambda) ergs = sed.calcErgs(bp) log10_ergs = np.log10(stefan_boltzmann_sigma) + 4.0*np.log10(temp) ergs_truth = np.power(10.0, log10_ergs) msg = '\ntemp:%e\nergs: %e\nergs_truth: %e' % (temp, ergs, ergs_truth) self.assertAlmostEqual(ergs/ergs_truth, 1.0, 3, msg=msg) # Now test it on a bandpass with throughput=0.25 and an wavelength # array that is not the same as the SED wavelen_arr = np.arange(10.0, 100000.0, 146.0) # in nm bp = Bandpass(wavelen=wavelen_arr, sb=0.25*np.ones(len(wavelen_arr))) wavelen_arr = np.arange(5.0, 200000.0, 17.0) log10_bb_factor = np.log10(2.0) + np.log10(planck_h) log10_bb_factor += 2.0*np.log10(speed_of_light) log10_bb_factor -= 5.0*(np.log10(wavelen_arr) - 7.0) # convert wavelen to cm for temp in np.arange(5000.0, 7000.0, 250.0): log10_exp_arg = np.log10(planck_h) + np.log10(speed_of_light) log10_exp_arg -= (np.log10(wavelen_arr) - 7.0) log10_exp_arg -= (np.log10(boltzmann_k) + np.log10(temp)) exp_arg = np.power(10.0, log10_exp_arg) log10_bose_factor = -1.0*np.log10(np.exp(exp_arg)-1.0) # the -7.0 below is because, otherwise, flambda will be in # ergs/s/cm^2/cm and we want ergs/s/cm^2/nm # # the np.pi comes from the integral in the 'Stefan-Boltzmann' # section of # https://en.wikipedia.org/wiki/Planck%27s_law#Stefan.E2.80.93Boltzmann_law # bb_flambda = np.pi*np.power(10.0, log10_bb_factor+log10_bose_factor-7.0) sed = Sed(wavelen=wavelen_arr, flambda=bb_flambda) ergs = sed.calcErgs(bp) log10_ergs = np.log10(stefan_boltzmann_sigma) + 4.0*np.log10(temp) ergs_truth = np.power(10.0, log10_ergs) msg = '\ntemp: %e\nergs: %e\nergs_truth: %e' % (temp,ergs, ergs_truth) self.assertAlmostEqual(ergs/ergs_truth, 0.25, 3, msg=msg)
def test_calcErgs(self): """ Test that calcErgs actually calculates the flux of a source in ergs/s/cm^2 by running it on black bodies with flat bandpasses and comparing to the Stefan-Boltzmann law. """ boltzmann_k = 1.3807e-16 # in ergs/Kelvin planck_h = 6.6261e-27 # in cm^2*g/s speed_of_light = 2.9979e10 # in cm/s stefan_boltzmann_sigma = 5.6705e-5 # in ergs/cm^2/s/Kelvin wavelen_arr = np.arange(10.0, 200000.0, 10.0) # in nm bp = Bandpass(wavelen=wavelen_arr, sb=np.ones(len(wavelen_arr))) log10_bb_factor = np.log10(2.0) + np.log10(planck_h) log10_bb_factor += 2.0 * np.log10(speed_of_light) log10_bb_factor -= 5.0 * (np.log10(wavelen_arr) - 7.0 ) # convert wavelen to cm for temp in np.arange(5000.0, 7000.0, 250.0): log10_exp_arg = np.log10(planck_h) + np.log10(speed_of_light) log10_exp_arg -= (np.log10(wavelen_arr) - 7.0) log10_exp_arg -= (np.log10(boltzmann_k) + np.log10(temp)) exp_arg = np.power(10.0, log10_exp_arg) log10_bose_factor = -1.0 * np.log10(np.exp(exp_arg) - 1.0) # the -7.0 below is because, otherwise, flambda will be in # ergs/s/cm^2/cm and we want ergs/s/cm^2/nm # # the np.pi comes from the integral in the 'Stefan-Boltzmann' # section of # https://en.wikipedia.org/wiki/Planck%27s_law#Stefan.E2.80.93Boltzmann_law # bb_flambda = np.pi * np.power( 10.0, log10_bb_factor + log10_bose_factor - 7.0) sed = Sed(wavelen=wavelen_arr, flambda=bb_flambda) ergs = sed.calcErgs(bp) log10_ergs = np.log10( stefan_boltzmann_sigma) + 4.0 * np.log10(temp) ergs_truth = np.power(10.0, log10_ergs) msg = '\ntemp:%e\nergs: %e\nergs_truth: %e' % (temp, ergs, ergs_truth) self.assertAlmostEqual(ergs / ergs_truth, 1.0, 3, msg=msg) # Now test it on a bandpass with throughput=0.25 and an wavelength # array that is not the same as the SED wavelen_arr = np.arange(10.0, 100000.0, 146.0) # in nm bp = Bandpass(wavelen=wavelen_arr, sb=0.25 * np.ones(len(wavelen_arr))) wavelen_arr = np.arange(5.0, 200000.0, 17.0) log10_bb_factor = np.log10(2.0) + np.log10(planck_h) log10_bb_factor += 2.0 * np.log10(speed_of_light) log10_bb_factor -= 5.0 * (np.log10(wavelen_arr) - 7.0 ) # convert wavelen to cm for temp in np.arange(5000.0, 7000.0, 250.0): log10_exp_arg = np.log10(planck_h) + np.log10(speed_of_light) log10_exp_arg -= (np.log10(wavelen_arr) - 7.0) log10_exp_arg -= (np.log10(boltzmann_k) + np.log10(temp)) exp_arg = np.power(10.0, log10_exp_arg) log10_bose_factor = -1.0 * np.log10(np.exp(exp_arg) - 1.0) # the -7.0 below is because, otherwise, flambda will be in # ergs/s/cm^2/cm and we want ergs/s/cm^2/nm # # the np.pi comes from the integral in the 'Stefan-Boltzmann' # section of # https://en.wikipedia.org/wiki/Planck%27s_law#Stefan.E2.80.93Boltzmann_law # bb_flambda = np.pi * np.power( 10.0, log10_bb_factor + log10_bose_factor - 7.0) sed = Sed(wavelen=wavelen_arr, flambda=bb_flambda) ergs = sed.calcErgs(bp) log10_ergs = np.log10( stefan_boltzmann_sigma) + 4.0 * np.log10(temp) ergs_truth = np.power(10.0, log10_ergs) msg = '\ntemp: %e\nergs: %e\nergs_truth: %e' % (temp, ergs, ergs_truth) self.assertAlmostEqual(ergs / ergs_truth, 0.25, 3, msg=msg)