def buildMirror(mirrorDir, addLosses=True): """ Build a mirror throughput curve. Assumes there are *Losses.dat subdirectory with loss files and a m*_Ideal.dat file with the mirror throughput. Returns a bandpass object. If addLosses is True, the *_Ideal.dat file is multiplied by the *_Losses/*.dat files. """ # Read the mirror reflectance curve. mirrorfile = glob(os.path.join(mirrorDir, 'm*Ideal.dat')) if len(mirrorfile) != 1: raise ValueError('Expected a single mirror file in directory %s, found: ' %mirrorDir, mirrorfile) mirrorfile = mirrorfile[0] mirror = Bandpass() mirror.readThroughput(mirrorfile) if addLosses: loss = _readLosses(mirrorDir) wavelen, sb = mirror.multiplyThroughputs(loss.wavelen, loss.sb) mirror.setBandpass(wavelen, sb) # Verify that no values go significantly below zero. belowzero = np.where(mirror.sb < 0) # If there are QE values significantly < 0, raise an exception. if mirror.sb[belowzero] < belowZeroThreshhold: raise ValueError('Found values in mirror response significantly below zero') # If they are just small errors in interpolation, set to zero. mirror.sb[belowzero] = 0 return mirror
def buildVendorDetector(vendorDir, addLosses=True): """ Builds a detector response from the files in vendorDir, by reading the *_QE.dat and *_Losses subdirectory for a single version of the detector. Returns a Bandpass object. If addLosses is True, the QE curve is multiplied by the losses in the *Losses.dat files. If addLosses is False, the QE curve does not have any losses included. """ # Read the QE file. qefile = glob(os.path.join(vendorDir, '*_QE.dat')) if len(qefile) != 1: raise ValueError('Expected a single QE file in this directory, found: ', qefile) qefile = qefile[0] qe = Bandpass() qe.readThroughput(qefile) if addLosses: loss = _readLosses(vendorDir) wavelength, sb = qe.multiplyThroughputs(loss.wavelen, loss.sb) qe.setBandpass(wavelength, sb) # Verify that no values go significantly below zero. belowzero = np.where(qe.sb < 0) # If there are QE values significantly < 0, raise an exception. if qe.sb[belowzero] < belowZeroThreshhold: raise ValueError('Found values in QE response significantly below zero.') # If they are just small errors in interpolation, set to zero. qe.sb[belowzero] = 0 return qe
def buildLens(lensDir, addLosses=True): """ Build the lens throughput curve from the files in lensDir. Returns a bandpass object. The coatings for the lens are in *_Coatings, the loss files are in *_Losses. The borosilicate glass throughput is in l*_Glass.dat; this file is smoothed using the savitzsky_golay function. The glass response is multiplied by the coatings and (if addLosses is True), also the loss curves. """ lens = Bandpass() # Read the glass base file. glassfile = glob(os.path.join(lensDir, 'l*_Glass.dat')) if len(glassfile) != 1: raise ValueError('Expected a single glass file in this directory, found: ', glassfile) glassfile = glassfile[0] glass = Bandpass() glass.readThroughput(glassfile) # Smooth the glass response. smoothSb = savitzky_golay(glass.sb, 31, 3) lens = Bandpass() lens.setBandpass(glass.wavelen, smoothSb) # Read the broad band antireflective (BBAR) coatings files. bbars = _readCoatings(lensDir) # Multiply the bbars by the glass. wavelen, sb = lens.multiplyThroughputs(bbars.wavelen, bbars.sb) lens.setBandpass(wavelen, sb) # Add losses. if addLosses: loss = _readLosses(lensDir) wavelen, sb = lens.multiplyThroughputs(loss.wavelen, loss.sb) lens.setBandpass(wavelen, sb) # Verify that no values go significantly below zero. belowzero = np.where(lens.sb < 0) # If there are QE values significantly < 0, raise an exception. if lens.sb[belowzero] < belowZeroThreshhold: raise ValueError('Found values in lens throughput significantly below zero.') # If they are just small errors in interpolation, set to zero. lens.sb[belowzero] = 0 return lens
'filter_%s.dat' % bp_name), dtype=throughput_dtype) for np_component in np_component_list: interped_throughput = np.interp(np_filter['wav_nm'], np_component['wav_nm'], np_component['throughput']) np_filter['throughput'] *= interped_throughput if _LSST_STACK_INSTALLED: filter_bp = Bandpass() filter_bp.readThroughput( os.path.join(bp_dir, 'filter_%s.dat' % bp_name)) wav, sb = optics_bp.multiplyThroughputs(filter_bp.wavelen, filter_bp.sb) bp = Bandpass(wavelen=wav, sb=sb) # integrate the SED over the total system throughput flambda = np.interp(np_filter['wav_nm'], np_sed['wav_nm'], np_sed['flambda']) phys_params = PhysicalParameters() phot = flambda * np_filter['wav_nm'] / (phys_params.planck * phys_params.lightspeed * 1.0e9) integral = 0.5 * ( (phot[1:] * np_filter['throughput'][1:] + phot[:-1] * np_filter['throughput'][:-1]) * (np_filter['wav_nm'][1:] - np_filter['wav_nm'][:-1])).sum() effarea = np.pi * (6.423 * 100.0 / 2.0)**2
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)