예제 #1
0
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
예제 #2
0
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 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 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
예제 #5
0
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
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
예제 #7
0
                                               '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
예제 #8
0
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)