Exemplo n.º 1
0
def make_data_cube(
    detectid=None,
    coords=None,
    shotid=None,
    pixscale=0.25 * u.arcsec,
    imsize=30.0 * u.arcsec,
    wave_range=[3470, 5540],
    dwave=2.0,
    dcont=50.0,
    convolve_image=True,
    ffsky=True,
    subcont=False,
):
    """
    Function to make a datacube from either a detectid or from a
    coordinate/shotid combination.
    
    Paramaters
    ----------
    detectid: int
        detectid from the continuum or lines catalog. Default is
        None. Provide a coords/shotid combo if this isn't given
    coords: SkyCoords object
        coordinates to define the centre of the data cube
    pixscale: astropy angle quantity
        plate scale
    imsize: astropy angle quantity
        spatial length of cube (equal dims is only option)
    wave_range: list
        start and stop value for the wavelength range in Angstrom
    dwave
        step in wavelength range in Angstrom
    convolve_image: bool
         option to convolve image with shotid seeing
    ffsky: bool
        option to use full frame calibrated fibers. Default is
        True.
    subcont: bool
        option to subtract continuum. Default is False. This
        will measure the continuum 50AA below and above the
        input wave_range
    dcont
        width in angstrom to measure the continuum. Default is to
        measure 50 AA wide regions on either side of the line  

    Returns
    -------
    hdu: PrimaryHDU object
        the data cube 3D array and associated 3d header
        Units are '10^-17 erg cm-2 s-1 per spaxel'

    Examples
    --------

    Can either pass in a detectid:

    >>> detectid_obj=2101602788
    >>> hdu = make_data_cube( detectid=detectid_obj)
    >>> hdu.writeto( str(detectid_obj) + '.fits', overwrite=True)

    or can put in an SkyCoord object:

    >>> star_coords = SkyCoord(9.625181, -0.043587, unit='deg')
    >>> hdu = make_data_cube( coords=star_coords[0], shotid=20171016108, dwave=2.0)
    >>> hdu.writeto( 'star.fits', overwrite=True)
    
    """
    global config, detecth5, surveyh5

    if detectid is not None:
        detectid_obj = detectid
        det_info = detecth5.root.Detections.read_where(
            'detectid == detectid_obj')[0]
        shotid = det_info["shotid"]
        coords = SkyCoord(det_info["ra"], det_info["dec"], unit="deg")

        if coords is None or shotid is None:
            print("Provide a detectid or both a coords and shotid")

    E = Extract()
    E.load_shot(shotid, fibers=False)

    # get spatial dims:
    ndim = int(imsize / pixscale)
    center = int(ndim / 2)

    # get wave dims:
    nwave = int((wave_range[1] - wave_range[0]) / dwave + 1)

    w = wcs.WCS(naxis=3)
    w.wcs.crval = [coords.ra.deg, coords.dec.deg, wave_range[0]]
    w.wcs.crpix = [center, center, 1]
    w.wcs.ctype = ["RA---TAN", "DEC--TAN", "WAVE"]
    w.wcs.cdelt = [-pixscale.to(u.deg).value, pixscale.to(u.deg).value, dwave]

    rad = imsize.to(u.arcsec).value

    info_result = E.get_fiberinfo_for_coord(coords, radius=rad, ffsky=False)
    ifux, ifuy, xc, yc, ra, dec, data, error, mask = info_result

    # get ifu center:
    ifux_cen, ifuy_cen = E.convert_radec_to_ifux_ifuy(ifux, ifuy, ra, dec,
                                                      coords.ra.deg,
                                                      coords.dec.deg)

    # get FWHM and PA

    surveyh5 = tb.open_file(config.surveyh5, "r")
    shotid_obj = shotid

    pa = surveyh5.root.Survey.read_where("shotid == shotid_obj")["pa"][0]

    if convolve_image:
        fwhm = surveyh5.root.Survey.read_where(
            "shotid == shotid_obj")["fwhm_virus"][0]
    else:
        fwhm = 1.8  # just a dummy variable as convolve_image=False

    surveyh5.close()

    # add in rotation
    sys_rot = 1.55
    rot = 360. - (90. + pa + sys_rot)
    w.wcs.crota = [0, rot, 0]
    #    rrot = np.deg2rad(rot)
    #    w.wcs.pc = [[np.cos(rrot),
    #                 np.sin(rrot),0],
    #                [-1.0*np.sin(rrot),
    #                 np.cos(rrot),0], [0,0,0]]

    im_cube = np.zeros((nwave, ndim, ndim))

    wave_i = wave_range[0]
    i = 0

    while wave_i <= wave_range[1]:
        try:
            im_src = E.make_narrowband_image(
                ifux_cen,
                ifuy_cen,
                ifux,
                ifuy,
                data,
                mask,
                scale=pixscale.to(u.arcsec).value,
                wrange=[wave_i, wave_i + dwave],
                nchunks=1,
                seeing_fac=fwhm,
                convolve_image=convolve_image,
                boxsize=imsize.to(u.arcsec).value,
            )

            im_slice = im_src[0]

            if subcont:
                zarray_blue = E.make_narrowband_image(
                    ifux_cen,
                    ifuy_cen,
                    ifux,
                    ifuy,
                    data,
                    mask,
                    seeing_fac=fwhm,
                    scale=pixscale.to(u.arcsec).value,
                    boxsize=imsize.to(u.arcsec).value,
                    nchunks=2,
                    wrange=[wave_i - dcont, wave_i],
                    convolve_image=convolve_image,
                )
                zarray_red = E.make_narrowband_image(
                    ifux_cen,
                    ifuy_cen,
                    ifux,
                    ifuy,
                    data,
                    mask,
                    seeing_fac=fwhm,
                    nchunks=2,
                    scale=pixscale.to(u.arcsec).value,
                    boxsize=imsize.to(u.arcsec).value,
                    wrange=[wave_i + dwave, wave_i + dwave + dcont],
                    convolve_image=convolve_image,
                )

                im_cont = (zarray_blue[0] + zarray_red[0]) / (2 * dcont)
                im_slice = im_src[0] - dwave * im_cont

            im_cube[i, :, :] = im_slice

        except Exception:
            im_cube[i, :, :] = np.zeros((ndim, ndim))
        wave_i += dwave
        i += 1

    hdu = fits.PrimaryHDU(im_cube, header=w.to_header())

    E.close()

    return hdu
Exemplo n.º 2
0
def make_narrowband_image(
    detectid=None,
    coords=None,
    shotid=None,
    pixscale=0.25 * u.arcsec,
    imsize=30.0 * u.arcsec,
    wave_range=None,
    convolve_image=True,
    ffsky=True,
    subcont=False,
    dcont=50.,
    include_error=False,
):
    """
    Function to make narrowband image from either a detectid or from a
    coordinate/shotid combination.
    
    Paramaters
    ----------
    detectid: int
        detectid from the continuum or lines catalog. Default is
        None. Provide a coords/shotid combo if this isn't given
    coords: SkyCoords object
        coordinates to define the centre of the data cube
    pixscale: astropy angle quantity
         plate scale
    imsize: astropy angle quantity
        image size
    wave_range: list or None
        start and stop value for the wavelength range in Angstrom.
        If not given, the detectid linewidth is used
    convolve_image: bool
        option to convolve image with shotid seeing
    ffsky: bool
        option to use full frame calibrated fibers. Default is
        True.
    subcont: bool
        option to subtract continuum. Default is False. This
        will measure the continuum 50AA below and above the
        input wave_range
    dcont
        width in angstrom to measure the continuum. Default is to
        measure 50 AA wide regions on either side of the line
    include_error bool
        option to include error array

    Returns
    -------
    hdu: PrimaryHDU object
        the 2D summed data array and associated 2d header
        Units are '10^-17 erg cm-2 s-1'
        If include_error=True will include addiional hdu
    Examples
    --------

    For a specific detectid:
    >>> hdu = make_narrowband_image(detectid=2101046271)
    
    For a SkyCoords object. You must provide shotid and
    wavelength range

    >>> coords = SkyCoord(188.79312, 50.855747, unit='deg')
    >>> wave_obj = 4235.84 #in Angstrom
    >>> hdu = make_narrowband_image(coords=coords,
                                    shotid=20190524021,
                                    wave_range=[wave_obj-10, wave_obj+10])
    """
    global config, detecth5, surveyh5

    if detectid is not None:

        detectid_obj = detectid
        det_info = detecth5.root.Detections.read_where(
            'detectid == detectid_obj')[0]

        shotid_obj = det_info["shotid"]
        wave_obj = det_info["wave"]
        linewidth = det_info["linewidth"]
        wave_range = [wave_obj - 2.0 * linewidth, wave_obj + 2.0 * linewidth]
        coords = SkyCoord(det_info["ra"], det_info["dec"], unit="deg")
    elif coords is not None:
        if shotid is not None:
            shotid_obj = shotid
        else:
            print("Provide a shotid")
        if wave_range is None:
            print("Provide a wavelength range to collapse. \
            Example wave_range=[4500,4540]")
    else:
        print("Provide a detectid or both a coords and shotid")

    fwhm = surveyh5.root.Survey.read_where(
        "shotid == shotid_obj")["fwhm_virus"][0]
    pa = surveyh5.root.Survey.read_where("shotid == shotid_obj")["pa"][0]

    E = Extract()
    E.load_shot(shotid_obj, fibers=False)

    # get spatial dims:
    ndim = int(imsize / pixscale)
    center = int(ndim / 2)

    rad = imsize.to(u.arcsec).value  # convert to arcsec value, not quantity

    info_result = E.get_fiberinfo_for_coord(coords, radius=rad, ffsky=ffsky)
    ifux, ifuy, xc, yc, ra, dec, data, error, mask = info_result

    # get ifu center:
    ifux_cen, ifuy_cen = E.convert_radec_to_ifux_ifuy(ifux, ifuy, ra, dec,
                                                      coords.ra.deg,
                                                      coords.dec.deg)

    if include_error:
        zarray = E.make_narrowband_image(
            ifux_cen,
            ifuy_cen,
            ifux,
            ifuy,
            data,
            mask,
            error=error,
            seeing_fac=fwhm,
            scale=pixscale.to(u.arcsec).value,
            boxsize=imsize.to(u.arcsec).value,
            wrange=wave_range,
            convolve_image=convolve_image,
        )
        imslice = zarray[0]
        imerror = zarray[1]
    else:
        zarray = E.make_narrowband_image(
            ifux_cen,
            ifuy_cen,
            ifux,
            ifuy,
            data,
            mask,
            seeing_fac=fwhm,
            scale=pixscale.to(u.arcsec).value,
            boxsize=imsize.to(u.arcsec).value,
            wrange=wave_range,
            convolve_image=convolve_image,
        )

        imslice = zarray[0]

    if subcont:
        zarray_blue = E.make_narrowband_image(
            ifux_cen,
            ifuy_cen,
            ifux,
            ifuy,
            data,
            mask,
            seeing_fac=fwhm,
            scale=pixscale.to(u.arcsec).value,
            boxsize=imsize.to(u.arcsec).value,
            wrange=[wave_range[0] - dcont - 10, wave_range[0] - 10],
            convolve_image=convolve_image,
        )

        zarray_red = E.make_narrowband_image(
            ifux_cen,
            ifuy_cen,
            ifux,
            ifuy,
            data,
            mask,
            seeing_fac=fwhm,
            scale=pixscale.to(u.arcsec).value,
            boxsize=imsize.to(u.arcsec).value,
            wrange=[wave_range[1] + 10, wave_range[1] + dcont + 10],
            convolve_image=convolve_image,
        )

        dwave = wave_range[1] - wave_range[0]
        im_cont = (zarray_blue[0] + zarray_red[0]) / (2 * dcont)

        imslice = zarray[0] - dwave * im_cont

    w = wcs.WCS(naxis=2)
    imsize = imsize.to(u.arcsec).value
    w.wcs.crval = [coords.ra.deg, coords.dec.deg]
    w.wcs.crpix = [center, center]
    w.wcs.ctype = ["RA---TAN", "DEC--TAN"]
    w.wcs.cdelt = [-pixscale.to(u.deg).value, pixscale.to(u.deg).value]

    # get rotation:
    sys_rot = 1.55
    rot = 360. - (90. + pa + sys_rot)
    rrot = np.deg2rad(rot)

    #    w.wcs.crota = [ 0, rot]

    w.wcs.pc = [[np.cos(rrot), np.sin(rrot)],
                [-1.0 * np.sin(rrot), np.cos(rrot)]]

    hdu = fits.PrimaryHDU(imslice, header=w.to_header())
    E.close()
    if include_error:
        hdu_error = fits.ImageHDU(imerror, header=w.to_header())
        hdu_x = fits.ImageHDU(zarray[2], header=w.to_header())
        hdu_y = fits.ImageHDU(zarray[3], header=w.to_header())
        return fits.HDUList([hdu, hdu_error, hdu_x, hdu_y])
    else:
        return hdu