Beispiel #1
0
def renormalize_visit_spectrum(norm_spec, spec_err, label_guess,
                               NN_coeffs_norm, NN_coeffs_flux, v_helio):
    '''
    Because visit spectra are initially normalized using a different routine than 
        is implemented in the main spectral modle, then need to be normalized again.
    
    This first obtains the continuum for a synthetic single-star model with parameters
        given by label_guess, multiplies the spectrum by this continuum, and then 
        normalizes that "unnormalized" spectrum using the default normalization routine. 
        It isn't critical that label_guess be vary accurate, since it only supplies a 
        smooth continuum that is divided out again anyway, but it can help a bit. Normally,
        label_guess is obtained by fitting a single-star model to the combined spectrum.
    '''
    star_labels = label_guess[:5]
    labels = np.concatenate([star_labels, [v_helio]])
    flux_spec_synth = spectral_model.get_surface_flux_spectrum_single_star(
        labels=labels,
        NN_coeffs_norm=NN_coeffs_norm,
        NN_coeffs_flux=NN_coeffs_flux)
    cont_synth = utils.get_apogee_continuum(wavelength=wavelength,
                                            spec=flux_spec_synth,
                                            spec_err=None,
                                            cont_pixels=cont_pixels)
    flux_spec_data = cont_synth * norm_spec
    cont_data = utils.get_apogee_continuum(wavelength=wavelength,
                                           spec=flux_spec_data,
                                           spec_err=spec_err,
                                           cont_pixels=cont_pixels)
    renormalized_spec = flux_spec_data / cont_data
    return renormalized_spec
Beispiel #2
0
def get_normalized_spectrum_N(labels,
                              NN_coeffs_norm,
                              NN_coeffs_flux,
                              NN_coeffs_Teff2_logg2,
                              NN_coeffs_R,
                              spec_err=None):
    '''Determine Teff and logg of the non-primary stars, predict the normalized spectra of 
    the primary,secondary,thrid,etc. stars, add them together, and normalize. 
    
    labels = [Teff, logg, [Fe/H], [Mg/Fe], vmacro1, dv1] 
            + [q2, vmacro2, dv2] + .. [qN, vmacroN, dvN]
            '''

    Teff1, logg1, feh, alphafe, vmacro1, dv1 = labels[:6]
    labels1 = [Teff1, logg1, feh, alphafe, vmacro1, dv1]
    f_lambda1 = get_unnormalized_spectrum_single_star(
        labels=labels1,
        NN_coeffs_norm=NN_coeffs_norm,
        NN_coeffs_flux=NN_coeffs_flux,
        NN_coeffs_R=NN_coeffs_R)

    f_lambda_N = f_lambda1.copy()
    ## now determin the number of additional components, each with q, vmacro, dv
    N = int((len(labels) - 6) / 3)
    for n in range(N):
        q, vmacro2, dv2 = labels[6 + n * 3:9 + n * 3]
        Teff2, logg2 = get_Teff2_logg2_NN(
            labels=[Teff1, logg1, feh, q],
            NN_coeffs_Teff2_logg2=NN_coeffs_Teff2_logg2)
        labels2 = [Teff2, logg2, feh, alphafe, vmacro2, dv2]
        f_lambda2 = get_unnormalized_spectrum_single_star(
            labels=labels2,
            NN_coeffs_norm=NN_coeffs_norm,
            NN_coeffs_flux=NN_coeffs_flux,
            NN_coeffs_R=NN_coeffs_R)
        f_lambda_N += f_lambda2

    cont = utils.get_apogee_continuum(wavelength=wavelength,
                                      spec=f_lambda_N,
                                      spec_err=spec_err,
                                      cont_pixels=cont_pixels)
    f_lambda_N_norm = f_lambda_N / cont
    return f_lambda_N_norm
Beispiel #3
0
def get_surface_flux_spectrum_single_star(labels, NN_coeffs_norm,
                                          NN_coeffs_flux):
    '''
    (a) predict the normalized spectrum, presumably using a data-driven model, 
    (b) predict the unnormalized spectrum, using e.g. Kurucz models
    (c) get the continuum from the unnormalized spectrum
    (d) multiply the normalized spectrum by said continuum.
    (e) redshift as necessary
    The result is an unnormalized spectrum which has the high-frequency features 
        (e.g. lines) from the data-driven model and low-frequency features (continuum)
        from the synthetic model. 
    
    This has units of surface flux; i.e., it is not scaled by the radius of the star
    labels: [Teff, logg, feh, alpha, vmacro, dv] (dv is the velocity offset)
    '''
    c_aa_s = 2.998e18  # speed of light in angstroms/sec
    dv = labels[-1]

    # first, get f_nu in surface flux units.
    # labels for the synthetic spectra are [Teff, logg, feh, alpha]
    # and for the data driven spectra, [Teff, logg, feh, alpha, vmacro]
    fnu = get_spectrum_from_neural_net(labels[:-2],
                                       NN_coeffs=NN_coeffs_flux,
                                       normalized=False)
    cont = utils.get_apogee_continuum(wavelength=wavelength,
                                      spec=fnu,
                                      spec_err=None,
                                      cont_pixels=cont_pixels)
    fnu_norm = get_spectrum_from_neural_net(labels[:-1],
                                            NN_coeffs=NN_coeffs_norm,
                                            normalized=True)
    fnu_good = fnu_norm * cont  # in erg cm^-2 s^-1 Hz^-1 Sr^-1

    # change from fnu to f_lambda. The factor of 4*pi gets rid of the Sr^-1.
    f_lambda = fnu_good * (
        c_aa_s / wavelength**2) * 4 * np.pi  # in erg cm^-2 s^-1 AA^-1
    f_shifted = utils.doppler_shift(wavelength=wavelength,
                                    flux=f_lambda,
                                    dv=dv)

    return f_shifted
Beispiel #4
0
def get_normalized_spectrum_single_star(labels,
                                        NN_coeffs_norm,
                                        NN_coeffs_flux,
                                        spec_err=None):
    '''
    Predict a spectrum in unnormalized space. Then normalize it using the observed
    flux uncertainties, so that it can be compared to the observed spectrum 
    self-consistently. 
    
    labels = [Teff, logg, [Fe/H], [Mg/Fe], v_macro, dv]
    '''
    f_lambda = get_surface_flux_spectrum_single_star(
        labels=labels,
        NN_coeffs_norm=NN_coeffs_norm,
        NN_coeffs_flux=NN_coeffs_flux)
    cont = utils.get_apogee_continuum(wavelength=wavelength,
                                      spec=f_lambda,
                                      spec_err=spec_err,
                                      cont_pixels=cont_pixels)
    f_lambda_norm = f_lambda / cont
    return f_lambda_norm
Beispiel #5
0
def get_normalized_spectrum_binary(labels,
                                   NN_coeffs_norm,
                                   NN_coeffs_flux,
                                   NN_coeffs_Teff2_logg2,
                                   NN_coeffs_R,
                                   spec_err=None):
    '''
    Determine Teff and logg of the secondary, predict the normalized spectra of the primary
    and the secondary, add them together, and normalize. 
    
    labels = [Teff1, logg1, [Fe/H], [Mg/Fe], q, v_macro1, v_macro2, dv1, dv2]
    spec_err is an array of uncertainties that is used in normalization only. If you just
        want to predict the theoretical spectrum, it isn't needed. But if you're fitting
        an observed spectrum, this should be the uncertainties of the observed spectrum,
        so that the observed and model spectra are normalized self-consistently. 
    '''
    Teff1, logg1, feh, alphafe, q, vmacro1, vmacro2, dv1, dv2 = labels
    Teff2, logg2 = get_Teff2_logg2_NN(
        labels=[Teff1, logg1, feh, q],
        NN_coeffs_Teff2_logg2=NN_coeffs_Teff2_logg2)
    labels1 = [Teff1, logg1, feh, alphafe, vmacro1, dv1]
    labels2 = [Teff2, logg2, feh, alphafe, vmacro2, dv2]

    f_lambda1 = get_unnormalized_spectrum_single_star(
        labels=labels1,
        NN_coeffs_norm=NN_coeffs_norm,
        NN_coeffs_flux=NN_coeffs_flux,
        NN_coeffs_R=NN_coeffs_R)
    f_lambda2 = get_unnormalized_spectrum_single_star(
        labels=labels2,
        NN_coeffs_norm=NN_coeffs_norm,
        NN_coeffs_flux=NN_coeffs_flux,
        NN_coeffs_R=NN_coeffs_R)
    f_lambda_binary = f_lambda1 + f_lambda2
    cont = utils.get_apogee_continuum(wavelength=wavelength,
                                      spec=f_lambda_binary,
                                      spec_err=spec_err,
                                      cont_pixels=cont_pixels)
    f_lambda_binary_norm = f_lambda_binary / cont
    return f_lambda_binary_norm
Beispiel #6
0
def read_batch_of_spectra(batch_count, batch_size=10000):
    '''
    Download a bunch of *combined* spectra in one go. Set the uncertainties to a large
    value in bad pixels, normalize, and save the batch locally. 
    '''
    # read in the catalog catalog
    catalog, fibers = read_apogee_catalog()
    catalog = catalog[batch_count * batch_size:(batch_count + 1) * batch_size]
    fibers = fibers[batch_count * batch_size:(batch_count + 1) * batch_size]
    _COMBINED_INDEX = 1

    nspec = len(catalog)
    spec = np.zeros((nspec, 7214))
    specerr = np.zeros((nspec, 7214))

    # Set up bad pixel mask
    badcombpixmask = bitmask.badpixmask() + 2**bitmask.apogee_pixmask_int(
        "SIG_SKYLINE")

    # loop through the individual targets
    for ii in range(nspec):
        field = catalog['FIELD'][ii].decode()
        ap_id = catalog['APOGEE_ID'][ii].decode()
        loc_id = catalog['LOCATION_ID'][ii]
        print('processing target %d with id %s' % (ii, ap_id))

        try:
            if loc_id == 1:
                temp1 = apread.apStar(field,
                                      ap_id,
                                      ext=1,
                                      header=False,
                                      aspcapWavegrid=True)
                temp2 = apread.apStar(field,
                                      ap_id,
                                      ext=2,
                                      header=False,
                                      aspcapWavegrid=True)
                temp3 = apread.apStar(field,
                                      ap_id,
                                      ext=3,
                                      header=False,
                                      aspcapWavegrid=True)
            else:
                temp1 = apread.apStar(loc_id,
                                      ap_id,
                                      ext=1,
                                      header=False,
                                      aspcapWavegrid=True)
                temp2 = apread.apStar(loc_id,
                                      ap_id,
                                      ext=2,
                                      header=False,
                                      aspcapWavegrid=True)
                temp3 = apread.apStar(loc_id,
                                      ap_id,
                                      ext=3,
                                      header=False,
                                      aspcapWavegrid=True)

            if temp1.shape[0] > 6000:
                spec[ii] = temp1
                specerr[ii] = temp2
                mask = temp3
            else:
                spec[ii] = temp1[_COMBINED_INDEX]
                specerr[ii] = temp2[_COMBINED_INDEX]
                mask = temp3[_COMBINED_INDEX]

            # Inflate uncertainties for bad pixels
            specerr[ii, (mask & (badcombpixmask)) != 0] += \
                100. * np.mean(spec[ii, np.isfinite(spec[ii])])

            # Inflate pixels with high SNR to 0.5
            highsnr = spec[ii] / specerr[ii] > 200.
            specerr[ii, highsnr] = 0.005 * np.fabs(spec[ii, highsnr])

            # Continuum-normalize
            cont = utils.get_apogee_continuum(wavelength=wavelength,
                                              spec=spec[ii],
                                              spec_err=specerr[ii],
                                              cont_pixels=cont_pixels)
            spec[ii] /= cont
            specerr[ii] /= cont
            specerr[ii, highsnr] = 0.005
        except OSError:
            print('target could not be found!')
            continue

    # save spectra
    np.savez('spectra/apogee_all_spectra_' + str(batch_count) + '.npz',
             wavelength=wavelength,
             spectra=spec,
             spec_err=specerr,
             apogee_id=np.array(catalog["APOGEE_ID"]),
             apogee_fiber_id=fibers)
Beispiel #7
0
def get_combined_spectrum_single_object(apogee_id,
                                        catalog=None,
                                        save_local=False):
    '''
    apogee_id should be a byte-like object; i.e b'2M13012770+5754582'
    This downloads a single combined spectrum and the associated error array,
        and it normalizes both. 
    '''
    # read in the allStar catalog if you haven't already
    if catalog is None:
        catalog, fibers = read_apogee_catalog()

    # Set up bad pixel mask
    badcombpixmask = bitmask.badpixmask() + 2**bitmask.apogee_pixmask_int(
        "SIG_SKYLINE")
    _COMBINED_INDEX = 1

    msk = np.where(catalog['APOGEE_ID'] == apogee_id)[0]
    if not len(msk):
        raise ValueError(
            'the desired Apogee ID was not found in the allStar catalog.')

    field = catalog['FIELD'][msk[0]].decode()
    ap_id = apogee_id.decode()
    loc_id = catalog['LOCATION_ID'][msk[0]]

    if loc_id == 1:
        temp1 = apread.apStar(field,
                              ap_id,
                              ext=1,
                              header=False,
                              aspcapWavegrid=True)
        temp2 = apread.apStar(field,
                              ap_id,
                              ext=2,
                              header=False,
                              aspcapWavegrid=True)
        temp3 = apread.apStar(field,
                              ap_id,
                              ext=3,
                              header=False,
                              aspcapWavegrid=True)
    else:
        temp1 = apread.apStar(loc_id,
                              ap_id,
                              ext=1,
                              header=False,
                              aspcapWavegrid=True)
        temp2 = apread.apStar(loc_id,
                              ap_id,
                              ext=2,
                              header=False,
                              aspcapWavegrid=True)
        temp3 = apread.apStar(loc_id,
                              ap_id,
                              ext=3,
                              header=False,
                              aspcapWavegrid=True)

    if temp1.shape[0] > 6000:
        spec = temp1
        specerr = temp2
        mask = temp3
    else:
        spec = temp1[_COMBINED_INDEX]
        specerr = temp2[_COMBINED_INDEX]
        mask = temp3[_COMBINED_INDEX]

    # Inflate uncertainties for bad pixels
    specerr[(mask & (badcombpixmask)) != 0] += 100 * np.mean(
        spec[np.isfinite(spec)])

    # Inflate pixels with high SNR to 0.5
    highsnr = spec / specerr > 200.
    specerr[highsnr] = 0.005 * np.fabs(spec[highsnr])

    # Continuum-normalize
    cont = utils.get_apogee_continuum(wavelength=wavelength,
                                      spec=spec,
                                      spec_err=specerr,
                                      cont_pixels=cont_pixels)
    spec /= cont
    specerr /= cont
    specerr[highsnr] = 0.005

    if save_local:
        np.savez('spectra/combined/spectrum_ap_id_' + str(apogee_id.decode()) +
                 '_.npz',
                 spectrum=spec,
                 spec_err=specerr)
    return spec, specerr