コード例 #1
0
def addlines2spec(wavelength, wl_line, fl_line, resolution,
                  scale_spec=1., debug=False):
    """ Create a spectrum with a set of (gaussian) emission lines.
    
    Parameters
    ----------
    wavelength : np.array
        wavelength vector of the input spectrum
    wl_line, fl_line : np.arrays
        wavelength and flux of each individual line
    resolution : np.float
        resolution of the spectrograph. In other words, the lines
        will have a FWHM equal to:
        fwhm_line = wl_line / resolution
    scale_spec : np.float
        rescale all the  normalization of the final spectrum.
        Default scale_spec=1.
    debug : boolean
        If True will show debug plots

    Returns
    -------
    line_spec : np.array
        Spectrum with lines

    """
    line_spec = np.zeros_like(wavelength)
    wl_line_min, wl_line_max = np.min(wavelength), np.max(wavelength)
    good_lines = (wl_line>wl_line_min) & (wl_line<wl_line_max)
    wl_line_good = wl_line[good_lines]
    fl_line_good = fl_line[good_lines]

    # define sigma of the gaussians
    sigma = wl_line_good / resolution / 2.355

    msgs.info("Creating line spectrum")
    for ii in np.arange(len(wl_line_good)):
        line_spec += scale_spec*fl_line_good[ii]*\
                     np.exp(-np.power((wl_line_good[ii]-wavelength),2.)/(2.*np.power(sigma[ii],2.)))

    if debug:
        utils.pyplot_rcparams()
        msgs.info("Plot of the line spectrum.")
        plt.figure()
        plt.plot(wavelength, line_spec,
                 color='navy', linestyle='-', alpha=0.8,
                 label=r'Spectrum with lines included')
        plt.legend()
        plt.xlabel(r'Wavelength')
        plt.ylabel(r'Flux')
        msgs.info("Close the Figure to continue.")
        plt.show(block=True)
        plt.close()
        utils.pyplot_rcparams_default()

    return line_spec
コード例 #2
0
def blackbody(wavelength, T_BB=250., debug=False):
    """ Given wavelength [in microns] and Temperature in Kelvin
    it returns the black body emission.

    Parameters
    ----------
    wavelength : np.array
        wavelength vector in microns
    T_BB : float 
        black body temperature in Kelvin. Default is set to:
        T_BB = 250.

    Returns
    -------
    blackbody : np.array
        spectral radiance of the black body in cgs units:
        B_lambda = 2.*h*c^2/lambda^5.*(1./(exp(h*c/(lambda*k_b*T_BB))-1.)
    blackbody_counts : np.array
        Same as above but in flux density
    """

    # Define constants in cgs
    PLANCK = astropy.constants.h.cgs.value  # erg*s
    C_LIGHT = astropy.constants.c.cgs.value  # cm/s
    K_BOLTZ = astropy.constants.k_B.cgs.value  # erg/K
    RADIAN_PER_ARCSEC = 1. / 3600. * np.pi / 180.

    msgs.info("Creating BB spectrum at T={}K".format(T_BB))
    lam = wavelength / 1e4  # convert wave in cm.
    blackbody_pol = 2. * PLANCK * np.power(C_LIGHT, 2) / np.power(lam, 5)
    blackbody_exp = np.exp(PLANCK * C_LIGHT / (lam * K_BOLTZ * T_BB)) - 1.
    blackbody = blackbody_pol / blackbody_exp
    blackbody_counts = blackbody / (PLANCK * C_LIGHT / lam) * 1e-4 \
                 * np.power(RADIAN_PER_ARCSEC, 2.)

    if debug:
        utils.pyplot_rcparams()
        msgs.info("Plot of the blackbody spectrum.")
        plt.figure()
        plt.plot(wavelength,
                 blackbody,
                 color='navy',
                 linestyle='-',
                 alpha=0.8,
                 label=r'T_BB={}'.format(T_BB))
        plt.legend()
        plt.xlabel(r"Wavelength [micron]")
        plt.ylabel(r"Spectral Radiance")
        plt.title(r"Planck's law")
        msgs.info("Close the Figure to continue.")
        plt.show(block=True)
        plt.close()
        utils.pyplot_rcparams_default()

    return blackbody, blackbody_counts
コード例 #3
0
def conv2res(wavelength, flux, resolution, central_wl='midpt', debug=False):
    """Convolve an imput spectrum to a specific resolution. This is only
    approximate. It takes a fix FWHM for the entire spectrum given by:
    fwhm = wl_cent / resolution

    Parameters
    ----------
    wavelength : np.array
        wavelength
    flux : np.array
        flux
    resolution : np.float
        resolution of the spectrograph
    central_wl 
        if 'midpt' the central pixel of wavelength is used, otherwise
        the central_wl will be used.
    debug : boolean
        If True will show debug plots

    Returns
    -------
    flux_convolved :np.array
        Resulting flux after convolution
    px_sigma : float
        Size of the sigma in pixels at central_wl
    px_bin : float
        Size of one pixel at central_wl
    """

    if central_wl == 'midpt':
        wl_cent = np.median(wavelength)
    else:
        wl_cent = np.float(central_wl)
    wl_sigma = wl_cent / resolution / 2.355
    wl_bin = np.abs((wavelength - np.roll(wavelength, 1))[np.where(
        np.abs(wavelength - wl_cent) == np.min(np.abs(wavelength - wl_cent)))])
    msgs.info("The binning of the wavelength array at {} is: {}".format(
        wl_cent, wl_bin[0]))
    px_bin = wl_bin[0]
    px_sigma = wl_sigma / px_bin

    msgs.info("Covolving with a Gaussian kernel with sigma = {} pixels".format(
        px_sigma))
    gauss_kernel = Gaussian1DKernel(px_sigma)

    flux_convolved = convolve(flux, gauss_kernel)

    if debug:
        utils.pyplot_rcparams()
        msgs.info("Spectrum Convolved at R = {}".format(resolution))
        plt.figure()
        plt.plot(wavelength,
                 flux,
                 color='navy',
                 linestyle='-',
                 alpha=0.8,
                 label=r'Original')
        plt.plot(wavelength,
                 flux_convolved,
                 color='crimson',
                 linestyle='-',
                 alpha=0.8,
                 label=r'Convolved')
        plt.legend()
        plt.xlabel(r'Wavelength')
        plt.ylabel(r'Flux')
        plt.title(r'Spectrum Convolved at R = {}'.format(resolution))
        msgs.info("Close the Figure to continue.")
        plt.show(block=True)
        plt.close()
        utils.pyplot_rcparams_default()

    return flux_convolved, px_sigma, px_bin
コード例 #4
0
def optical_modelThAr(resolution,
                      waveminmax=(3000., 10500.),
                      dlam=40.0,
                      flgd=True,
                      thar_outfile=None,
                      debug=False):
    """ Generate a model of a ThAr lamp in the uvb/optical. This is based on the
    Murphy et al. ThAr spectrum. Detailed information are here:
    http://astronomy.swin.edu.au/~mmurphy/thar/index.html
    Everythins is smoothed at the given resolution.

    Parameters
    ----------
    resolution : np.float
        resolution of the spectrograph. The ThAr lines will have a 
        FWHM equal to:
        fwhm_line = wl_line / resolution
    waveminmax : tuple
        wavelength range in angstrom to be covered by the model.
        Default is: (3000.,10500.)
    dlam : 
        bin to be used to create the wavelength grid of the model.
        If flgd='True' it is a bin in velocity (km/s). If flgd='False'
        it is a bin in linear space (microns).
        Default is: 40.0 (with flgd='True')
    flgd : boolean
        if flgd='True' (default) wavelengths are created with 
        equal steps in log space. If 'False', wavelengths will be
        created wit equal steps in linear space.
    thar_outfile : str
        name of the fits file where the model sky spectrum will be stored.
        default is 'None' (i.e., no file will be written).
    debug : boolean
        If True will show debug plots

    Returns
    -------
    wave, thar_model : np.arrays
        wavelength (in Ang.) and flux of the final model of the ThAr lamp emission.
    """

    # Create the wavelength array:
    wv_min = waveminmax[0]
    wv_max = waveminmax[1]
    if flgd:
        msgs.info("Creating wavelength vector in velocity space.")
        velpix = dlam  # km/s
        loglam = np.log10(1.0 + velpix / 299792.458)
        wave = np.power(10.,
                        np.arange(np.log10(wv_min), np.log10(wv_max), loglam))
    else:
        msgs.info("Creating wavelength vector in linear space.")
        wave = np.arange(wv_min, wv_max, dlam)

    msgs.info("Add in ThAr lines")
    th_wv, th_fx = thar_lines()

    # select spectral region
    filt_wl = (th_wv >= wv_min) & (th_wv <= wv_max)
    # calculate sigma at the mean wavelenght of the ThAr spectrum
    mn_wv = np.mean(th_wv[filt_wl])
    # Convolve to the instrument resolution. This is only
    # approximate.
    smooth_fx, dwv, thar_dwv = conv2res(th_wv,
                                        th_fx,
                                        resolution,
                                        central_wl=mn_wv,
                                        debug=debug)
    # Interpolate over input wavelengths
    interp_thar = scipy.interpolate.interp1d(th_wv,
                                             smooth_fx,
                                             kind='cubic',
                                             fill_value='extrapolate')
    thar_spec = interp_thar(wave)

    # remove negative artifacts
    thar_spec[thar_spec < 0.] = 0.
    # Remove regions of the spectrum outside the wavelength covered by the ThAr model
    if wv_min < np.min(th_wv):
        msgs.warn("Model of the ThAr spectrum outside the template coverage.")
        thar_spec[wave < np.min(th_wv)] = 0.
    if wv_max < np.max(th_wv):
        msgs.warn("Model of the ThAr spectrum outside the template coverage.")
        thar_spec[wave > np.max(th_wv)] = 0.

    if thar_outfile is not None:
        msgs.info("Saving the ThAr model in: {}".format(thar_outfile))
        hdu = fits.PrimaryHDU(np.array(thar_spec))
        header = hdu.header
        if flgd:
            header['CRVAL1'] = np.log10(wv_min)
            header['CDELT1'] = loglam
            header['DC-FLAG'] = 1
        else:
            header['CRVAL1'] = wv_min
            header['CDELT1'] = dlam
            header['DC-FLAG'] = 0
        hdu.writeto(thar_outfile, overwrite=True)

    if debug:
        utils.pyplot_rcparams()
        msgs.info(
            "Plot of the Murphy et al. template at R={}".format(resolution))
        plt.figure()
        plt.plot(th_wv,
                 th_fx,
                 color='navy',
                 linestyle='-',
                 alpha=0.3,
                 label=r'Original')
        plt.plot(th_wv,
                 smooth_fx,
                 color='crimson',
                 linestyle='-',
                 alpha=0.6,
                 label=r'Convolved at R={}'.format(resolution))
        plt.plot(wave,
                 thar_spec,
                 color='maroon',
                 linestyle='-',
                 alpha=1.0,
                 label=r'Convolved at R={} and resampled'.format(resolution))
        plt.legend()
        plt.xlabel(r'Wavelength [Ang.]')
        plt.ylabel(r'Emission')
        plt.title(r'Murphy et al. ThAr spectrum at R={}'.format(resolution))
        msgs.info("Close the Figure to continue.")
        plt.show(block=True)
        plt.close()
        utils.pyplot_rcparams_default()

    return np.array(wave), np.array(thar_spec)
コード例 #5
0
def nearIR_modelsky(resolution,
                    waveminmax=(0.8, 2.6),
                    dlam=40.0,
                    flgd=True,
                    nirsky_outfile=None,
                    T_BB=250.,
                    SCL_BB=1.,
                    SCL_OH=1.,
                    SCL_H2O=10.,
                    WAVE_WATER=2.3,
                    debug=False):
    """ Generate a model sky in the near-IR. This includes a continuum model
    to match to gemini broadband level, a black body at T_BB, OH lines, and 
    H2O lines (but only at lambda>WAVE_WATER). Everythins is smoothed at the
    given resolution.

    Parameters
    ----------
    resolution : np.float
        resolution of the spectrograph. The OH and H2O lines will have a 
        FWHM equal to:
        fwhm_line = wl_line / resolution
    waveminmax : tuple
        wavelength range in microns to be covered by the model.
        Default is: (0.8, 2.6)
    dlam : 
        bin to be used to create the wavelength grid of the model.
        If flgd='True' it is a bin in velocity (km/s). If flgd='False'
        it is a bin in linear space (microns).
        Default is: 40.0 (with flgd='True')
    flgd : boolean
        if flgd='True' (default) wavelengths are created with 
        equal steps in log space. If 'False', wavelengths will be
        created wit equal steps in linear space.
    nirsky_outfile : str
        name of the fits file where the model sky spectrum will be stored.
        default is 'None' (i.e., no file will be written).
    T_BB : float 
        black body temperature in Kelvin. Default is set to:
        T_BB = 250.
    SCL_BB : float
        scale factor for modelling the sky black body emssion.
        Default: SCL_BB=1.
    SCL_OH : float
        scale factor for modelling the OH emssion.
        Default: SCL_OH=1.
    SCL_H2O : float
        scale factor for modelling the H2O emssion.
        Default: SCL_H2O=10.
    WAVE_WATER : float
        wavelength (in microns) at which the H2O are inclued.
        Default: WAVE_WATER = 2.3
    debug : boolean
        If True will show debug plots

    Returns
    -------
    wave, sky_model : np.arrays
        wavelength (in Ang.) and flux of the final model of the sky.
    """

    # Create the wavelength array:
    wv_min = waveminmax[0]
    wv_max = waveminmax[1]
    if flgd:
        msgs.info("Creating wavelength vector in velocity space.")
        velpix = dlam  # km/s
        loglam = np.log10(1.0 + velpix / 299792.458)
        wave = np.power(10.,
                        np.arange(np.log10(wv_min), np.log10(wv_max), loglam))
    else:
        msgs.info("Creating wavelength vector in linear space.")
        wave = np.arange(wv_min, wv_max, dlam)

    # Calculate transparency
    # trans = transparency(wave, debug=False)

    # Empirical match to gemini broadband continuum level
    logy = -0.55 - 0.55 * (wave - 1.0)
    y = np.power(10., logy)

    msgs.info("Add in a blackbody for the atmosphere.")
    bb, bb_counts = blackbody(wave, T_BB=T_BB, debug=debug)
    bb_counts = bb_counts

    msgs.info("Add in OH lines")
    oh_wv, oh_fx = oh_lines()
    # produces better wavelength solutions with 1.0 threshold
    msgs.info("Selecting stronger OH lines")
    filt_oh = oh_fx > 1.
    oh_wv, oh_fx = oh_wv[filt_oh], oh_fx[filt_oh]
    # scale_spec was added to match the XIDL code
    ohspec = addlines2spec(wave,
                           oh_wv,
                           oh_fx,
                           resolution=resolution,
                           scale_spec=((resolution / 1000.) / 40.),
                           debug=debug)

    if wv_max > WAVE_WATER:
        msgs.info("Add in H2O lines")
        h2o_wv, h2o_rad = h2o_lines()
        filt_h2o = (h2o_wv > wv_min - 0.1) & (h2o_wv < wv_max + 0.1)
        h2o_wv = h2o_wv[filt_h2o]
        h2o_rad = h2o_rad[filt_h2o]
        # calculate sigma at the mean wavelenght of the H2O spectrum
        filt_h2o_med = h2o_wv > WAVE_WATER
        mn_wv = np.mean(h2o_wv[filt_h2o_med])
        # Convolve to the instrument resolution. This is only
        # approximate.
        smooth_fx, dwv, h2o_dwv = conv2res(h2o_wv,
                                           h2o_rad,
                                           resolution,
                                           central_wl=mn_wv,
                                           debug=debug)
        # Interpolate over input wavelengths
        interp_h2o = scipy.interpolate.interp1d(h2o_wv,
                                                smooth_fx,
                                                kind='cubic',
                                                fill_value='extrapolate')
        h2ospec = interp_h2o(wave)
        # Zero out below WAVE_WATER microns (reconsider)
        h2ospec[wave < WAVE_WATER] = 0.
        h2ospec[wave > np.max(h2o_wv)] = 0.
    else:
        h2ospec = np.zeros(len(wave), dtype='float')

    sky_model = y + bb_counts * SCL_BB + ohspec * SCL_OH + h2ospec * SCL_H2O

    if nirsky_outfile is not None:
        msgs.info("Saving the sky model in: {}".format(nirsky_outfile))
        hdu = fits.PrimaryHDU(np.array(sky_model))
        header = hdu.header
        if flgd:
            header['CRVAL1'] = np.log10(wv_min)
            header['CDELT1'] = loglam
            header['DC-FLAG'] = 1
        else:
            header['CRVAL1'] = wv_min
            header['CDELT1'] = dlam
            header['DC-FLAG'] = 0
        hdu.writeto(nirsky_outfile, overwrite=True)

    if debug:
        utils.pyplot_rcparams()
        msgs.info("Plot of the sky emission at R={}".format(resolution))
        plt.figure()
        plt.plot(wave,
                 sky_model,
                 color='black',
                 linestyle='-',
                 alpha=0.8,
                 label=r'Sky Model')
        plt.plot(wave,
                 y,
                 color='darkorange',
                 linestyle='-',
                 alpha=0.6,
                 label=r'Continuum')
        plt.plot(wave,
                 bb_counts * SCL_BB,
                 color='green',
                 linestyle='-',
                 alpha=0.6,
                 label=r'Black Body at T={}K'.format(T_BB))
        plt.plot(wave,
                 ohspec * SCL_OH,
                 color='darkviolet',
                 linestyle='-',
                 alpha=0.6,
                 label=r'OH')
        plt.plot(wave,
                 h2ospec * SCL_H2O,
                 color='dodgerblue',
                 linestyle='-',
                 alpha=0.6,
                 label=r'H2O')
        plt.legend()
        plt.xlabel(r'Wavelength [microns]')
        plt.ylabel(r'Emission')
        plt.title(r'Sky Emission Spectrum at R={}'.format(resolution))
        msgs.info("Close the Figure to continue.")
        plt.show(block=True)
        plt.close()
        utils.pyplot_rcparams_default()

    return np.array(wave * 10000.), np.array(sky_model)
コード例 #6
0
def transparency(wavelength, debug=False):
    """ Interpolate the atmospheric transmission model in the IR over
    a given wavelength (in microns) range.

    Parameters
    ----------
    wavelength : np.array
        wavelength vector in microns
    debug : boolean
        If True will show debug plots

    Returns
    -------
    transparency : np.array
        Transmission of the sky over the considered wavelength rage.
        1. means fully transparent and 0. fully opaque
    """

    msgs.info("Reading in the atmospheric transmission model")
    transparency = np.loadtxt(
        data.get_skisim_filepath('atm_transmission_secz1.5_1.6mm.dat'))
    wave_mod = transparency[:, 0]
    tran_mod = transparency[:, 1]

    # Limit model between 0.8 and np.max(wavelength) microns
    filt_wave_mod = (wave_mod > 0.8) & (wave_mod < np.max(wavelength))
    wave_mod = wave_mod[filt_wave_mod]
    tran_mod = tran_mod[filt_wave_mod]

    # Interpolate over input wavelengths
    interp_tran = scipy.interpolate.interp1d(wave_mod,
                                             tran_mod,
                                             kind='cubic',
                                             fill_value='extrapolate')
    transmission = interp_tran(wavelength)
    transmission[wavelength < 0.9] = 1.

    # Clean for spourious values due to interpolation
    transmission[transmission < 0.] = 0.
    transmission[transmission > 1.] = 1.

    if debug:
        utils.pyplot_rcparams()
        msgs.info("Plot of the sky transmission template")
        plt.figure()
        plt.plot(wave_mod,
                 tran_mod,
                 color='navy',
                 linestyle='-',
                 alpha=0.8,
                 label=r'Original')
        plt.plot(wavelength,
                 transmission,
                 color='crimson',
                 linestyle='-',
                 alpha=0.8,
                 label=r'Resampled')
        plt.legend()
        plt.xlabel(r'Wavelength [microns]')
        plt.ylabel(r'Transmission')
        plt.title(r' IR Transmission Spectra ')
        msgs.info("Close the Figure to continue.")
        plt.show(block=True)
        plt.close()
        utils.pyplot_rcparams_default()

    # Returns
    return transmission
コード例 #7
0
ファイル: arc_old.py プロジェクト: thespacedoctor/PypeIt
def fit2darc_old(all_wv, all_pix, all_orders, nspec, nspec_coeff=4, norder_coeff=4, sigrej=3.0, debug=False):
    """Routine to obtain the 2D wavelength solution for an echelle spectrograph. This is calculated from the spec direction
    pixelcentroid and the order number of identified arc lines. The fit is a simple least-squares with rejections.
    This is a port of the XIDL code: x_fit2darc.pro

    Parameters
    ----------
    all_wv: np.array
     wavelength of the identified lines
    all_pix: np.array
      y-centroid position of the identified lines
    all_orders: np.array
      order number of the identified lines
    nspec: int
      Size of the image in the spectral direction
    nspec_coeff : np.int
      order of the fitting along the spectral (pixel) direction for each order
    norder_coeff : np.int
      order of the fitting in the order direction
    sigrej: np.float
      sigma level for the rejection
    debug: boolean
      Extra plots to check the status of the procedure

    Returns:
    -------
    """


    # To use the legendre polynomial pixels and orders
    # need to be normalized in the -1,+1 range
    # Normalize pixels
    mnx = 0  # np.min(all_pix)
    mxx = float(nspec - 1)  # np.max(all_pix)
    norm_pixel = np.array([0.5 * (mnx + mxx), mxx - mnx])
    pix_nrm = 2. * (all_pix - norm_pixel[0]) / norm_pixel[1]
    # Normalize orders
    mnx, mxx = np.min(all_orders), np.max(all_orders)
    norm_order = np.array([0.5 * (mnx + mxx), mxx - mnx])
    orders_nrm = 2. * (all_orders - norm_order[0]) / norm_order[1]

    if debug:
        # set some plotting parameters
        utils.pyplot_rcparams()
        plt.figure(figsize=(7, 5))
        msgs.info("Plot identified lines")
        cm = plt.cm.get_cmap('RdYlBu_r')
        sc = plt.scatter(orders_nrm, pix_nrm, c=all_wv / 10000., cmap=cm)
        cbar = plt.colorbar(sc)
        cbar.set_label(r'Wavelength [$\mu$m]', rotation=270,
                       labelpad=20)
        plt.xlabel(r'Normalized Orders')
        plt.ylabel(r'Normalized Pixels')
        plt.title(r'Location of the identified lines')
        plt.show()

    # Setup some things for the fits
    all_wv_order = all_wv * all_orders
    work2d = np.zeros((nspec_coeff * norder_coeff, len(all_wv)), dtype=np.float64)
    worky = pydl.flegendre(pix_nrm, nspec_coeff)
    workt = pydl.flegendre(orders_nrm, norder_coeff)
    for i in range(norder_coeff):
        for j in range(nspec_coeff):
            work2d[j * norder_coeff + i, :] = worky[j, :] * workt[i, :]

    # ToDO add upper lower to inputs
    lower = np.abs(sigrej)
    upper = np.abs(sigrej)
    maxiter = 25
    iIter = 0
    qdone = False
    thismask = np.ones_like(all_wv, dtype=bool)
    while (not qdone) and (iIter < maxiter):
        coeffs, wv_order_mod = fit_double_poly(all_wv_order, work2d, thismask.astype(float), nspec_coeff, norder_coeff)
        thismask, qdone = pydl.djs_reject(all_wv_order, wv_order_mod, outmask=thismask,
                                          lower=np.float64(lower), upper=np.float64(upper), use_mad=True, sticky=True)
        iIter += 1
        if debug:
            utils.pyplot_rcparams()
            plt.figure(figsize=(7, 5))
            plt.axhline(y=np.average(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask]), color='r',
                        linestyle='--')
            plt.axhline(y=+np.std(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask]), color='r',
                        linestyle=':')
            plt.axhline(y=-np.std(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask]), color='r',
                        linestyle=':')
            plt.scatter(all_wv[~thismask] / 10000., wv_order_mod[~thismask] / all_orders[~thismask] - all_wv[~thismask],
                        marker="v", label=r'Rejected values')
            plt.scatter(all_wv[thismask] / 10000., wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask],
                        marker="v", label=r'Good values')
            plt.text(np.min(all_wv / 10000),
                     np.average(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask]),
                     r'Average={0:.1f}$\AA$'.format(
                         np.average(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask])),
                     ha="left", va="bottom",
                     bbox=dict(boxstyle="square", ec=(1., 0.5, 0.5), fc=(1., 0.8, 0.8), alpha=0.7, ))
            plt.text(np.max(all_wv / 10000), np.std(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask]),
                     r'Sigma={0:.1f}$\AA$'.format(
                         np.std(wv_order_mod[thismask] / all_orders[thismask] - all_wv[thismask])), ha="right",
                     va="bottom", bbox=dict(boxstyle="square", ec=(1., 0.5, 0.5), fc=(1., 0.8, 0.8), alpha=0.7, ))
            plt.legend()
            plt.title(r'Residuals after rejection iteration #{:d}'.format(iIter))
            plt.xlabel(r'Wavelength [$\mu$m]')
            plt.ylabel(r'Residuals [$\AA$]')
            plt.show()
    if iIter == maxiter:
        msgs.warn('Maximum number of iterations maxiter={:}'.format(maxiter) + ' reached in robust_polyfit_djs')

    # Final fit
    coeffs, wv_order_mod = fit_double_poly(all_wv_order, work2d,
                                           thismask.astype(float),
                                           nspec_coeff, norder_coeff)

    # Check quality
    resid = (wv_order_mod[thismask] - all_wv_order[thismask])
    fin_rms = np.sqrt(np.mean(resid ** 2))
    msgs.info("RMS: {0:.5f} Ang*Order#".format(fin_rms))

    orders = np.unique(all_orders)
    fit_dict = dict(coeffs=coeffs, orders=orders,
                    nspec_coeff=nspec_coeff, norder_coeff=norder_coeff,
                    pixel_cen=norm_pixel[0], pixel_norm=norm_pixel[1],
                    order_cen=norm_order[0], order_norm=norm_order[1],
                    nspec=nspec, all_pix=all_pix, all_wv=all_wv,
                    all_orders=all_orders, all_mask=thismask)

    if debug:
        fit2darc_global_qa(fit_dict)
        fit2darc_orders_qa(fit_dict)

    return fit_dict
コード例 #8
0
ファイル: arc_old.py プロジェクト: thespacedoctor/PypeIt
def fit2darc_orders_qa_old(fit_dict, outfile=None):
    """ QA on 2D fit of the wavelength solution of an Echelle spectrograph.
    Each panel contains a single order with the global fit and the
    residuals.

    Parameters
    ----------
    fit_dict: dict
      dict of the 2D arc solution
    outfile:
      parameter for QA

    Returns
    -------
    """

    msgs.info("Creating QA for 2D wavelength solution")

    utils.pyplot_rcparams()

    # Extract info from fit_dict
    nspec = fit_dict['nspec']
    orders = fit_dict['orders']
    pixel_norm = fit_dict['pixel_norm']
    pixel_cen = fit_dict['pixel_cen']
    nspec_coeff = fit_dict['nspec_coeff']
    norder_coeff = fit_dict['norder_coeff']
    all_wv = fit_dict['all_wv']
    all_pix = fit_dict['all_pix']
    all_orders = fit_dict['all_orders']
    thismask = fit_dict['all_mask']
    resid_wl_global = []

    # Define pixels array
    all_pixels = np.arange(nspec)

    # set the size of the plot
    nrow = np.int(2)
    ncol = np.int(np.ceil(len(orders ) /2.))
    fig = plt.figure(figsize=( 5 *ncol , 6 *nrow))

    outer = gridspec.GridSpec(nrow, ncol, wspace=0.3, hspace=0.2)

    for ii_row in range(nrow):
        for ii_col in range(ncol):
            if (ii_ro w *ncol + ii_col) < len(orders):
                inner = gridspec.GridSpecFromSubplotSpec(2, 1,
                                                         height_ratios=[2 ,1], width_ratios=[1],
                                                         subplot_spec=outer[ii_ro w *ncol + ii_col],
                                                         wspace=0.1, hspace=0.0)
                ax0 = plt.Subplot(fig, inner[0])
                ax1 = plt.Subplot(fig, inner[1], sharex=ax0)
                plt.setp(ax0.get_xticklabels(), visible=False)

                ii = orders[ii_ro w *ncol + ii_col]

                # define the color
                rr = (i i -np.max(orders) ) /(np.min(orders ) -np.max(orders))
                gg = 0.0
                bb = (i i -np.min(orders) ) /(np.max(orders ) -np.min(orders))

                # Evaluate function
                wv_order_mod = eval2dfit(fit_dict, all_pixels, ii)
                # Evaluate delta lambda
                dw l =(wv_order_mod[-1 ] -wv_order_mod[0] ) /i i /(all_pixels[-1 ] -all_pixels[0])

                # Estimate the residuals
                this_pix = all_pix[all_orders == ii]
                this_wv = all_wv[all_orders == ii]
                this_msk = thismask[all_orders == ii]

                wv_order_mod_resid = eval2dfit(fit_dict, this_pix, ii)
                resid_wl = (wv_order_mod_resi d /i i -this_wv)
                resid_wl_global = np.append(resid_wl_global ,resid_wl[this_msk])

                # Plot the fit
                ax0.set_title('Order = {0:0.0f}'.format(ii))
                ax0.plot(all_pixels, wv_order_mo d /i i /10000. ,color=(rr ,gg ,bb), linestyle='-',
                         linewidth=2.5)
                ax0.scatter(this_pix[~this_msk], (wv_order_mod_resid[~this_msk ] /i i /10000. )+ \
                            100 . *resid_wl[~this_msk ] /10000., marker='x', color='black', \
                            linewidth=2.5, s=16.)
                ax0.scatter(this_pix[this_msk], (wv_order_mod_resid[this_msk ] /i i /10000. )+ \
                            100 . *resid_wl[this_msk ] /10000., color=(rr ,gg ,bb), \
                            linewidth=2.5, s=16.)

                ax0.set_ylabel(r'Wavelength [$\mu$m]')

                # Plot the residuals
                ax1.scatter(this_pix[~this_msk] ,(resid_wl[~this_msk ] /dwl) ,marker='x', color='black', \
                            linewidth=2.5, s=16.)
                ax1.scatter(this_pix[this_msk], (resid_wl[this_msk ] /dwl), color=(rr ,gg ,bb), \
                            linewidth=2.5, s=16.)
                ax1.axhline(y=0., color=(rr ,gg ,bb), linestyle=':', linewidth=2.5)
                ax1.get_yaxis().set_label_coords(-0.15 ,0.5)

                rms_order = np.sqrt(np.mean((resid_wl[this_msk] )* *2))

                ax1.set_ylabel(r'Res. [pix]')

                ax0.text(0.1 ,0.9 ,r'RMS={0:.3f} Pixel'.format(rms_orde r /np.abs(dwl)) ,ha="left", va="top",
                         transform = ax0.transAxes)
                ax0.text(0.1 ,0.8 ,r'$\Delta\lambda$={0:.3f} Pixel/$\AA$'.format(np.abs(dwl)) ,ha="left", va="top",
                         transform = ax0.transAxes)
                ax0.get_yaxis().set_label_coords(-0.15 ,0.5)

                fig.add_subplot(ax0)
                fig.add_subplot(ax1)
コード例 #9
0
ファイル: arc_old.py プロジェクト: thespacedoctor/PypeIt
def fit2darc_global_qa_old(fit_dict, outfile=None):
    """ QA on 2D fit of the wavelength solution.

    Parameters
    ----------
    fit_dict: dict
      dict of the 2D arc solution
    outfile:
      parameter for QA

    Returns
    -------
    """

    msgs.info("Creating QA for 2D wavelength solution")

    utils.pyplot_rcparams()

    # Extract info from fit_dict
    nspec = fit_dict['nspec']
    orders = fit_dict['orders']
    pixel_norm = fit_dict['pixel_norm']
    pixel_cen = fit_dict['pixel_cen']
    nspec_coeff = fit_dict['nspec_coeff']
    norder_coeff = fit_dict['norder_coeff']
    all_wv = fit_dict['all_wv']
    all_pix = fit_dict['all_pix']
    all_orders = fit_dict['all_orders']
    thismask = fit_dict['all_mask']
    resid_wl_global = []

    # Define pixels array
    all_pixels = np.arange(nspec)

    # Define figure properties
    plt.figure(figsize=(8 ,5))

    # Variable where to store the max wavelength covered by the
    # spectrum
    mx = 0.

    # Loop over orders
    for ii in orders:

        # define the color
        rr = (i i -np.max(orders) ) /(np.min(orders ) -np.max(orders))
        gg = 0.0
        bb = (i i -np.min(orders) ) /(np.max(orders ) -np.min(orders))

        # evaluate solution
        wv_order_mod = eval2dfit(fit_dict, all_pixels, ii)

        # Plot solution
        plt.plot(wv_order_mo d /ii, all_pixels ,color=(rr ,gg ,bb),
                 linestyle='-', linewidth=2.5)

        # Evaluate residuals at each order
        this_pix = all_pix[all_orders == ii]
        this_wv = all_wv[all_orders == ii]
        this_msk = thismask[all_orders == ii]
        wv_order_mod_resid = eval2dfit(fit_dict, this_pix, ii)
        resid_wl = (wv_order_mod_resid /i i -this_wv)
        resid_wl_global = np.append(resid_wl_global ,resid_wl[this_msk])
        plt.scatter((wv_order_mod_resid[~this_msk ] /ii )+ \
                    100 . *resid_wl[~this_msk], this_pix[~this_msk], \
                    marker='x', color='black', linewidths=2.5, s=16.)
        plt.scatter((wv_order_mod_resid[this_msk ] /ii )+ \
                    100 . *resid_wl[this_msk], this_pix[this_msk], \
                    color=(rr ,gg ,bb), linewidth=2.5, s=16.)
        if np.max(wv_order_mod_resi d /ii) > mx :
            mx = np.max(wv_order_mod_resi d /ii)
コード例 #10
0
ファイル: sensfunc.py プロジェクト: tbowers7/PypeIt
    def write_QA(self):
        """
        Write out zeropoint QA files
        """
        utils.pyplot_rcparams()

        # Plot QA for zeropoint
        if 'Echelle' in self.spectrograph.pypeline:
            order_or_det = self.spectrograph.orders[np.arange(self.norderdet)]
            order_or_det_str = 'order'
        else:
            order_or_det = np.arange(self.norderdet) + 1
            order_or_det_str = 'det'

        spec_str = f' {self.spectrograph.name} {self.spectrograph.pypeline} ' \
                   f'{self.spectrograph.dispname} '
        zp_title = [
            'PypeIt Zeropoint QA for' + spec_str + order_or_det_str +
            f'={order_or_det[idet]}' for idet in range(self.norderdet)
        ]
        thru_title = [
            order_or_det_str + f'={order_or_det[idet]}'
            for idet in range(self.norderdet)
        ]

        is_odd = self.norderdet % 2 != 0
        npages = int(np.ceil(self.norderdet /
                             2)) if is_odd else self.norderdet // 2 + 1

        # TODO: PDF page logic is a bit complicated becauase we want to plot two
        # plots per page, but the number of pages depends on the number of
        # order/det. Consider just dumping out a set of plots or revamp once we
        # have a dashboard.
        with PdfPages(self.qafile) as pdf:
            for ipage in range(npages):
                figure, (ax1, ax2) = plt.subplots(2, figsize=(8.27, 11.69))
                if (2 * ipage) < self.norderdet:
                    flux_calib.zeropoint_qa_plot(
                        self.sens['SENS_WAVE'][2 * ipage],
                        self.sens['SENS_ZEROPOINT'][2 * ipage],
                        self.sens['SENS_ZEROPOINT_GPM'][2 * ipage],
                        self.sens['SENS_ZEROPOINT_FIT'][2 * ipage],
                        self.sens['SENS_ZEROPOINT_FIT_GPM'][2 * ipage],
                        title=zp_title[2 * ipage],
                        axis=ax1)
                if (2 * ipage + 1) < self.norderdet:
                    flux_calib.zeropoint_qa_plot(
                        self.sens['SENS_WAVE'][2 * ipage + 1],
                        self.sens['SENS_ZEROPOINT'][2 * ipage + 1],
                        self.sens['SENS_ZEROPOINT_GPM'][2 * ipage + 1],
                        self.sens['SENS_ZEROPOINT_FIT'][2 * ipage + 1],
                        self.sens['SENS_ZEROPOINT_FIT_GPM'][2 * ipage + 1],
                        title=zp_title[2 * ipage + 1],
                        axis=ax2)

                if self.norderdet == 1:
                    # For single order/det just finish up after the first page
                    ax2.remove()
                    pdf.savefig()
                    plt.close('all')
                elif (self.norderdet > 1) & (ipage < npages - 1):
                    # For multi order/det but not on the last page, finish up.
                    # No need to remove ax2 since there are always 2 plots per
                    # page except on the last page
                    pdf.savefig()
                    plt.close('all')
                else:
                    # For multi order/det but on the last page, add order/det
                    # summary plot to the final page Deal with even/odd page
                    # logic for axes
                    if is_odd:
                        # add order/det summary plot to axis 2 of current page
                        axis = ax2
                    else:
                        axis = ax1
                        ax2.remove()
                    for idet in range(self.norderdet):
                        # define the color
                        rr = (np.max(order_or_det) - order_or_det[idet]) \
                                / np.maximum(np.max(order_or_det) - np.min(order_or_det), 1)
                        gg = 0.0
                        bb = (order_or_det[idet] - np.min(order_or_det)) \
                                / np.maximum(np.max(order_or_det) - np.min(order_or_det), 1)
                        wave_gpm = self.sens['SENS_WAVE'][idet] > 1.0
                        axis.plot(self.sens['SENS_WAVE'][idet, wave_gpm],
                                  self.sens['SENS_ZEROPOINT_FIT'][idet,
                                                                  wave_gpm],
                                  color=(rr, gg, bb),
                                  linestyle='-',
                                  linewidth=2.5,
                                  label=thru_title[idet],
                                  zorder=5 * idet)

                    _wave_min = np.amin(self.sens['WAVE_MIN'])
                    _wave_max = np.amax(self.sens['WAVE_MAX'])

                    # If we are splicing, overplot the spliced zeropoint
                    if self.splice_multi_det:
                        wave_slice_gpm = (self.wave_splice >= _wave_min) \
                                            & (self.wave_splice <= _wave_max) \
                                            & (self.wave_splice > 1.0)
                        axis.plot(
                            self.wave_splice[wave_slice_gpm].flatten(),
                            self.zeropoint_splice[wave_slice_gpm].flatten(),
                            color='black',
                            linestyle='-',
                            linewidth=2.5,
                            label='Spliced Zeropoint',
                            zorder=30,
                            alpha=0.3)

                    wave_gpm = self.sens['SENS_WAVE'] > 1.0
                    axis.set_xlim((0.98 * _wave_min, 1.02 * _wave_max))
                    axis.set_ylim(
                        (0.95 *
                         np.amin(self.sens['SENS_ZEROPOINT_FIT'][wave_gpm]),
                         1.05 *
                         np.amax(self.sens['SENS_ZEROPOINT_FIT'][wave_gpm])))
                    axis.legend(fontsize=14)
                    axis.set_xlabel('Wavelength (Angstroms)')
                    axis.set_ylabel('Zeropoint (AB mag)')
                    axis.set_title('PypeIt Zeropoints for' + spec_str,
                                   fontsize=12)

                    pdf.savefig()
                    plt.close('all')

        # Plot throughput curve(s) for all orders/det
        fig = plt.figure(figsize=(12, 8))
        axis = fig.add_axes([0.1, 0.1, 0.8, 0.8])
        for idet in range(self.wave.shape[1]):
            # define the color
            rr = (np.max(order_or_det) - order_or_det[idet]) \
                    / np.maximum(np.max(order_or_det) - np.min(order_or_det), 1)
            gg = 0.0
            bb = (order_or_det[idet] - np.min(order_or_det)) \
                    / np.maximum(np.max(order_or_det) - np.min(order_or_det), 1)
            gpm = (self.throughput[:, idet] >= 0.0)
            axis.plot(self.wave[gpm, idet],
                      self.throughput[gpm, idet],
                      color=(rr, gg, bb),
                      linestyle='-',
                      linewidth=2.5,
                      label=thru_title[idet],
                      zorder=5 * idet)
        if self.splice_multi_det:
            axis.plot(self.wave_splice[wave_slice_gpm].flatten(),
                      self.throughput_splice[wave_slice_gpm].flatten(),
                      color='black',
                      linestyle='-',
                      linewidth=2.5,
                      label='Spliced Throughput',
                      zorder=30,
                      alpha=0.3)

        axis.set_xlim((0.98 * self.wave[self.throughput >= 0.0].min(),
                       1.02 * self.wave[self.throughput >= 0.0].max()))
        axis.set_ylim(
            (0.0, 1.05 * self.throughput[self.throughput >= 0.0].max()))
        axis.legend()
        axis.set_xlabel('Wavelength (Angstroms)')
        axis.set_ylabel('Throughput')
        axis.set_title('PypeIt Throughput for' + spec_str)
        fig.savefig(self.thrufile)