def apply_filters(wave, spec, **kwargs): """ Loads the detector QE and returns the values. band = 1 (default, 180-220 nm) band = 2 (260-320 nm) Syntax: wave, transmission = load_redfilter(band=1) """ from apply_transmission import apply_trans # Load filters ref_wave, reflectivity = load_reflectivity(**kwargs) qe_wave, qe = load_qe(**kwargs) red_wave, red_trans = load_redfilter(**kwargs) ref_flux = apply_trans(wave, spec, ref_wave, reflectivity / 100.) qe_flux = apply_trans(wave, ref_flux, qe_wave, qe) band_flux = apply_trans(wave, qe_flux, red_wave, red_trans) return band_flux
def optimize_filter(low_wave, high_wave, **kwargs): """ Optimizes out-of-band filters based on the input bandpass --- Inputs: low_wave = Lower side of bandpass (units consistent with length) high_wave = High side of the bandpass Option inputs: qe_band = Which QE file to use (Default is "1") target_ratio = Out-of-band to in-band counts (0.5) blue_filter = If there's an asymmetric filter, apply this to everything blue-ward of the low_wave """ from tdsat_telescope import load_qe, load_reflectivity from apply_transmission import apply_trans from zodi import load_zodi import astropy.units as ur # Check if the inputs make sense assert low_wave.unit.is_equivalent( ur.m), "Low-side wavelength does not have unit of length" assert high_wave.unit.is_equivalent( ur.m), "High-side wavelength does not have unit of length" qe_band = kwargs.pop('qe_band', 1) target_ratio = kwargs.pop('target_ratio', 0.5) blue_filter = kwargs.pop('blue_filter', False) diag = kwargs.pop('diag', False) # Load zodiacal background. Note that the out-of-band Zodi dominates over the # atmospheric lines (which are present here). Using the lowest Zodi background # represents the "worst case". zodi = load_zodi() # Load reflectivity and QE curves: ref_wave, reflectivity = load_reflectivity() qe_wave, qe = load_qe(band=qe_band) # Apply these to the Zodi spectrum: ref_flux = apply_trans(zodi['wavelength'], zodi['flux'], ref_wave, reflectivity / 100.) qe_flux = apply_trans(zodi['wavelength'], ref_flux, qe_wave, qe) # Make a "standard" red filter: rejection = 1.0 red_filter = make_red_filter(zodi['wavelength'], low_wave=low_wave, high_wave=high_wave, rejection=rejection, blue_filter=blue_filter, diag=diag) band_flux = apply_trans(zodi['wavelength'], qe_flux, zodi['wavelength'], red_filter) # Get the in-band, out-of-band ratio: in_band = band_flux[(zodi['wavelength'] > low_wave) & (zodi['wavelength'] < high_wave)].sum() out_of_band = band_flux[( (zodi['wavelength'] < low_wave) | (zodi['wavelength'] > high_wave)) & (zodi['wavelength'] < 1 * ur.micron)].sum() # Comput ratio: ratio = out_of_band / in_band target_rejection = (rejection * (target_ratio / ratio)).value if diag: print() print('Optimize filter diagnostics:') print('Low wave:{}'.format(low_wave)) print('High wave:{}'.format(high_wave)) print('Blue filter? {}'.format(blue_filter)) print('Target ratio: {}'.format(target_ratio)) print('Target rejection: {}'.format(target_rejection)) print() return target_rejection
def bgd_sky_qe_rate(**kwargs): """ Loads the zodiacal background and normalizes it at 500 nm to a particular flux level (low_zodi = 77, med_zodi = 300, high_zodi = 6000). See the docstring for load_zodi in zodi.py Optional Inputs (defaults): band = Bandpass (180-220)*ur.nm diameter=Telescope Diameter (21*u.cm) pixel_size=Angular size of the pixel (6*ur.arcsec) rejection = Out of band rejection (1e-3) diag = Diagnostics toggle (False) low_zodi = (True) medium_zodi = (False) high_zodi = (False) qe_band = Whivch QE curve to us (1 --> 180-220 nm, 2-->260-300 nm) blue_filter = Apply blue_side filter (False) Returns bgd_rate which is ph / s / pixel """ import astropy.units as ur import astropy.constants as cr import numpy as np from zodi import load_zodi, wavelength_to_energy from apply_transmission import apply_trans from tdsat_telescope import load_qe, load_reflectivity, load_redfilter, apply_filters from duet_filters import make_red_filter, optimize_filter # Set up units here for flux conversion below # fλ_unit = ur.erg/ur.cm**2/ur.s / ur.Angstrom # Spectral radiances per Hz or per angstrom # fλ_density_unit = fλ_unit / (ur.arcsec *ur.arcsec) diag = kwargs.pop('diag', False) pixel_size = kwargs.pop('pixel_size', 6 * ur.arcsec) pixel_area = pixel_size**2 diameter = kwargs.pop('diameter', 21. * ur.cm) Area_Tel = np.pi * (diameter.to(ur.cm) * 0.5)**2 low_zodi = kwargs.pop('low_zodi', True) med_zodi = kwargs.pop('med_zodi', False) high_zodi = kwargs.pop('high_zodi', False) band = kwargs.pop('band', [180, 220] * ur.nm) bandpass = np.abs(band[1] - band[0]) qe_band = kwargs.pop('qe_band', 1) blue_filter = kwargs.pop('blue_filter', False) filter_target = kwargs.pop('filter_target', 0.5) real_red = kwargs.pop('real_red', False) # effective_wavelength = (np.mean(band)).to(ur.AA) # ph_energy = (cr.h.cgs * cr.c.cgs / effective_wavelength.cgs).to(ur.eV) # Specified from Kristin. The highest Zodi that we hit is actually only 900 # (down from 6000 in previous iterations) sine any closer to the Sun we violate # our Sun-angle constraints. if low_zodi: zodi_level = 77 if med_zodi: zodi_level = 165 if high_zodi: zodi_level = 900 zodi = load_zodi(scale=zodi_level) wave = zodi['wavelength'] flux = zodi['flux'] if real_red: band_flux = apply_filters(zodi['wavelength'], zodi['flux'], band=qe_band, diag=diag, **kwargs) else: # Make the red filter low_wave = band[0] high_wave = band[1] rejection = optimize_filter(low_wave, high_wave, target_ratio=filter_target, blue_filter=blue_filter) red_trans = make_red_filter(wave, rejection=rejection, high_wave=high_wave, low_wave=low_wave, blue_filter=blue_filter) red_wave = wave # Load reflectivity and QE curves: ref_wave, reflectivity = load_reflectivity() qe_wave, qe = load_qe(band=qe_band) # Apply reflectivity and QE to the Zodi spectrum: ref_flux = apply_trans(zodi['wavelength'], zodi['flux'], ref_wave, reflectivity / 100.) qe_flux = apply_trans(zodi['wavelength'], ref_flux, qe_wave, qe) # Apply red filter band_flux = apply_trans(wave, qe_flux, red_wave, red_trans) # Assume bins are the same size: de = wave[1] - wave[0] # Convert to more convenient units: ph_flux = ((de * band_flux).cgs).to(1 / ((ur.cm**2 * ur.arcsec**2 * ur.s))) fluence = ph_flux.sum() BgdRatePerPix = pixel_area * fluence * Area_Tel if diag: print('Background Computation Integrating over Pixel Area') print('Telescope diameter: {}'.format(diameter)) print('Collecting Area: {}'.format(Area_Tel)) print('Band: {}'.format(band)) print('Bandpass: {}'.format(bandpass)) print() # print('Out-of-band rejection: {}'.format(rejection)) # print('Apply blue filter? {}'.format(blue_filter)) print() print('Pixel Area: {}'.format(pixel_area)) print() print('Background fluence per arcsec2 {}'.format(fluence)) print('Rate {}'.format(BgdRatePerPix)) return BgdRatePerPix