Beispiel #1
0
def smooth_image(hdu, smooth=2, header=None, mode='same'):
    """Takes a 2-dimensional FITS format image, and returns a smoothed version
    of it.

    @param hdu: input pyfits style HDU (header data unit) or just the numpy
        numpy format data image from pyfits HDU data attribute.
        If numpy format data cube is passed, then the header parameter
        should also be passed in.
    @param smooth: integer smoothing factor
    @param header: pyfits header object if needed
    @return A HDU instance with 2d output map in the data attribute of the HDU, 
        and the corresponding header in header attribute of the HDU.
        """
    if isinstance(hdu, astropy.io.fits.hdu.image.PrimaryHDU):
        #get data and header from the hdu
        data = hdu.data
        header = hdu.header
    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header,
                                            astropy.io.fits.header.Header):
            raise SculptArgumentError(
                'header',
                "Since you passed in data that is a numpy array, set header to a pyfits header type"
            )
        data = hdu
    else:
        raise SculptArgumentError(
            'hdu',
            "can only be one of pyfits.PrimaryHDU type or numpy ndarray")
    hdr = copy.copy(header)
    ny, nx = data.shape
    dt = copy.copy(data)
    dt = blur_image(dt, smooth, mode=mode)
    shape = dt.shape
    nyy, nxx = shape
    #cards = hdr.ascardlist()
    cards = hdr.cards
    card = cards['NAXIS1']
    card.value = shape[1]
    card = cards['CDELT1']
    card.value = card.value * float(nx) / float(nxx)
    card = cards['NAXIS2']
    card.value = shape[0]
    card = cards['CDELT2']
    card.value = card.value * float(ny) / float(nyy)

    return pyfits.PrimaryHDU(dt, header=hdr)
def transpose_cube(hdu, origin='xyv',
                   smooth=None):
    """
    Given a HDU this function transposes from origin (xyv, yxv, vxy or vyx)
    and makes a new hdu into  vxy or xyv cube
    If smooth is an integer the velocity axis is also smoothed 
    by the integral value
    """
    header = hdu.header
    data = hdu.data
    if origin not in ('xyv', 'yxv', 'vxy', 'vyx'):
        raise SculptArgumentError('transpose_cube', 'Origin should be one of xyv, yxv, vxy or vxy')
    if origin[2] == 'v':
        if header.get('CTYPE3') not in ('VELO-LSR', 'VELOCITY'):
            raise SculptArgumentError('header', 'Input Cube does not have Velocity in 3rd axis')
    else:
        if header.get('CTYPE1') not in ('VELO-LSR', 'VELOCITY'):
            raise SculptArgumentError('header', 'Input Cube does not have Velocity in 1st axis')
    data1 = transpose_data(data, origin=origin)
    header1 = transpose_header(header, origin=origin)
    if smooth is not None:
        data1, header1 = smooth(data1, header1, smooth,
                                origin=origin)
    return pyfits.PrimaryHDU(data=data1, header=header1)
Beispiel #3
0
def momentcube(hdu,
               v1,
               v2,
               header=None,
               chan=False,
               dontblank=False,
               kms=True,
               moment=0,
               returnrms=False,
               window=None):
    """
    Create 2d moment image from cube. The input cube is expected
    to be in the VLM format

    @param hdu: input pyfits style HDU (header data unit) or just the numpy
        numpy format data cube from pyfits HDU data attribute.
        This cube is expected to be in vlm format. If numpy format
        data cube is passed, then the header parameter should also be
        passed in.
    @type hdu: pyfits HDU or numpy array
    @param header: pyfits style header object that corresponds to the
        hdu data variable. This header parameter is only considered if
        the hdu parameter is a numpy array type rather than a pyfits HDU
        type
    @type header: pyfits header object
    @param v1: lower velocity to be used (If chan is set to True, this
        should be an integer). If chan is False, this is expected to be
        velocity expressed in kms (if the input parameter kms is True). If
        chan is False, and kms is False, v1 is treated with the same
        units as the FITS header describes.
    @param v2: upper velocity to be used. Same explanation as v1
    @param chan: If True, v1 and v2 are treated as channels. If False,
        they are treated as velocity
    @type chan: Boolean
    @param dontblank: By default, momentcube will use the BLANK fits
        header value and automatically zero blanked values in order
        to compute moments. If dontblank keyword is set, then
        such blanking is not performed.
    @type dontblank: Boolean
    @param kms: If True velocity units is in kms.
    @type kms: Boolean
    @param moment: which moment to extract. default is moment=0
        - moment=0 - integrated intensity
        - moment=1 - centroid velocity
        - moment=2 - width
    @type moment: int
    @param returnrms: If True, return image of the noise in the moment map
    @type returnrms: Boolean
    @param window: list of tuples (pairs) of channels/velocity to exclude
        from polynomial calculation in determining rms. If chan is set to
        True, these should be integers. If chan is False, this is expected to be
        velocity expressed in kms (if the input parameter kms is True). If
        chan is False, and kms is False, window is treated with the same
        units as the FITS header describes.
    @return: A HDU instance with 2d output map in the data attribute of the HDU, 
        and the corresponding header in header attribute of the HDU. If
        returnrms is True, returns the momentmap and rms image as a tuple.

    """
    if moment not in range(3):
        raise SculptArgumentError('moment', "moment can only be one of 0,1,2")
    if isinstance(hdu, astropy.io.fits.hdu.image.PrimaryHDU):
        #get data and header from the hdu
        data = hdu.data
        header = hdu.header
    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header,
                                            astropy.io.fits.header.Header):
            raise SculptArgumentError(
                'header',
                "Since you passed in data that is a numpy array, set header to a pyfits header type"
            )
        data = hdu
    else:
        raise SculptArgumentError(
            'hdu',
            "can only be one of pyfits.PrimaryHDU type or numpy ndarray")
    if returnrms and window is None:
        raise SculptArgumentError(
            'rms',
            'if returnrms is True, you need to specify a window to do the rms calculation in'
        )
    if returnrms and moment != 0:
        raise SculptArgumentError('rms',
                                  'For now, only moment=0 return rms image')
    # calculate the x-axis (velocity)
    crpix1 = sxpar(header, "CRPIX1")
    crval1 = sxpar(header, "CRVAL1")
    cdelt1 = sxpar(header, "CDELT1")
    if kms:
        #convert velocity to km/s
        crval1 = crval1 / 1000.
        cdelt1 = cdelt1 / 1000.
    ctype1 = sxpar(header, "CTYPE1")
    crpix2 = sxpar(header, "CRPIX2")
    crval2 = sxpar(header, "CRVAL2")
    cdelt2 = sxpar(header, "CDELT2")
    ctype2 = sxpar(header, "CTYPE2")
    crpix3 = sxpar(header, "CRPIX3")
    crval3 = sxpar(header, "CRVAL3")
    cdelt3 = sxpar(header, "CDELT3")
    ctype3 = sxpar(header, "CTYPE3")
    nv = sxpar(header, "NAXIS1")
    nx = sxpar(header, "NAXIS2")
    ny = sxpar(header, "NAXIS3")
    blank = sxpar(header, "BLANK")

    #cube = data.copy()
    if not dontblank and blank is not None:
        ind = numpy.where(data == blank)
        data[ind] = 0.0

    vind = numpy.zeros(nv, dtype=bool)
    if not chan:
        #get velocity axis
        velax = getaxes(header, 1)
        if v2 < v1:
            v1, v2 = v2, v1

    if chan:
        vind[v1:v2 + 1] = True
    else:
        vind = numpy.logical_and(velax >= v1, velax <= v2)

    N = len(numpy.where(vind)[0])
    print "The number of spectral channels used, N: %d" % N
    T = data[:, :, vind].sum(axis=2)  #T is integ intensity image now
    if moment >= 1:
        C = (data[:, :, vind] * velax[vind]).sum(axis=2)
        C = C / T  #centroid velocity definition
        if moment == 2:
            W = (data[:, :, vind] * velax[vind]**2.).sum(axis=2)
            W = W / T - C**2.

    hnew = header.copy()

    sxaddpar(hnew, "CRVAL1", crval2, comment="DEGREES")
    sxaddpar(hnew, "CRPIX1", crpix2)
    sxaddpar(hnew, "CDELT1", cdelt2, comment="DEGREES")
    sxaddpar(hnew, "CTYPE1", ctype2)
    sxaddpar(hnew, "CRVAL2", crval3, comment="DEGREES")
    sxaddpar(hnew, "CRPIX2", crpix3)
    sxaddpar(hnew, "CDELT2", cdelt3, comment="DEGREES")
    sxaddpar(hnew, "CTYPE2", ctype3)
    sxaddpar(hnew, "NAXIS", 2)
    sxaddpar(hnew, "NAXIS1", nx)
    sxaddpar(hnew, "NAXIS2", ny)
    sxaddpar(hnew, "NAXIS3", 1)
    sxaddpar(hnew, "NAXIS4", 1)
    if chan:
        vorc = 'CHANNEL'
    else:
        vorc = 'VELOCITY'
    sxaddpar(hnew, "VMIN", v1, "LOWER %s LIMIT" % vorc)
    sxaddpar(hnew, "VMAX", v2, "UPPER %s LIMIT" % vorc)
    sxaddpar(hnew, "MOMENT", moment, comment="Order of Moment")
    if moment == 0:
        units = "K.km/s"
    else:
        units = "km/s"
    sxaddpar(hnew, "BUNIT", units, "Units")
    for axis in xrange(3, 5):
        for attr in ('CRVAL', 'CRPIX', 'CDELT', 'CROTA', 'CTYPE', 'NAXIS'):
            sxdelpar(hnew, '%s%1d' % (attr, axis))
    if moment == 0:
        dt = T * abs(cdelt1)
    elif moment == 1:
        dt = C
    else:
        dt = W
    hdu = pyfits.PrimaryHDU(dt, header=hnew)
    if moment == 0 and returnrms:
        specrms = mkrmsimage(data, window=window, header=header)
        rms_data = specrms.data * abs(cdelt1) * math.sqrt(N)
        hrms = hnew.copy()
        sxaddhist(hrms, "WINDOW : %s; Window %s LIMITS" % (repr(window), vorc))
        rms = pyfits.PrimaryHDU(rms_data, header=hrms)
        return hdu, rms
    return hdu
Beispiel #4
0
def baseline(hdu,
             chan,
             windows,
             order=0,
             subtract=True,
             returnrms=True,
             kms=True):
    #this function needs to be passed a FITS HDU
    #with data in the (V,X,Y) format
    header = None
    if isinstance(hdu, pyfits.hdu.image.PrimaryHDU):
        # get data and header from the hdu
        header = hdu.header
        data = hdu.data

    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header, pyfits.header.Header):
            raise SculptArgumentError(
                'header',
                "Since you passed in data that is a numpy array, set header to a pyfits header type"
            )
        data = hdu

    shape = data.shape

    #windows over which to do the test for sigma values
    #basically excluse major lines you observe

    lenv, lenx, leny = shape
    #defaultswindow = ((100,200),(650,750))
    sigma = numpy.zeros((lenx, leny))

    x = numpy.arange(lenv)
    c_loop = 0

    # this commented section is the makermsimage way of selecting them
    # if someone wants to make a change regarding one being better, do it

    #    velax = getaxes(header, 1)
    #    indices = numpy.zeros(velax.shape, dtype=bool)
    #    for v1, v2 in window:
    #        if chan:
    #            indices[v1:v2] = True
    #        else:
    #            ind = numpy.logical_and(velax>= v1, velax<= v2)
    #            indices = numpy.logical_or(indices, ind)
    #    indices = numpy.logical_not(indices) # for indices to include in std calc

    for win in windows:
        if (len(win) != 2):
            print "Each element in the window list must be a 2-tuple"
        c1, c2 = win
        c1, c2 = sorted((c1, c2))
        ind = numpy.logical_and(x >= c1, x <= c2)
        if (c_loop == 0):
            final_ind = numpy.logical_or(ind, ind)
        else:
            final_ind = numpy.logical_or(final_ind, ind)

    x_windows = x[final_ind]
    for ix in range(lenx):
        for iy in range(leny):
            spectra = data[:, ix, iy]
            spec_windows = spectra[final_ind]

            p = numpy.polyfit(x_windows, spec_windows, order)
            spec_windows -= numpy.polyval(p, len(x_windows))

            sigma[ix, iy] = spec_windows.std()
            if (subtract):
                data[:, ix, iy] -= numpy.polyval(p, lenv)

    # this is the original input - with data reduced as needed
    hdu_orig = pyfits.hdu.image.PrimaryHDU(header=header, data=data)

    if returnrms:
        #the following grabs relevant information from the original header
        #and reproduces it in the RMSMap header shifted to account for
        #the different shape of the data
        crpix1 = sxpar(header, "CRPIX1")
        crval1 = sxpar(header, "CRVAL1")
        cdelt1 = sxpar(header, "CDELT1")
        if kms:
            #convert velocity to km/s
            crval1 = crval1 / 1000.
            cdelt1 = cdelt1 / 1000.
        ctype1 = sxpar(header, "CTYPE1")
        crpix2 = sxpar(header, "CRPIX2")
        crval2 = sxpar(header, "CRVAL2")
        cdelt2 = sxpar(header, "CDELT2")
        ctype2 = sxpar(header, "CTYPE2")
        crpix3 = sxpar(header, "CRPIX3")
        crval3 = sxpar(header, "CRVAL3")
        cdelt3 = sxpar(header, "CDELT3")
        ctype3 = sxpar(header, "CTYPE3")
        nv = sxpar(header, "NAXIS1")
        nx = sxpar(header, "NAXIS2")
        ny = sxpar(header, "NAXIS3")
        blank = sxpar(header, "BLANK")

        hnew = header.copy()

        sxaddpar(hnew, "CRVAL1", crval2, comment="DEGREES")
        sxaddpar(hnew, "CRPIX1", crpix2)
        sxaddpar(hnew, "CDELT1", cdelt2, comment="DEGREES")
        sxaddpar(hnew, "CTYPE1", ctype2)
        sxaddpar(hnew, "CRVAL2", crval3, comment="DEGREES")
        sxaddpar(hnew, "CRPIX2", crpix3)
        sxaddpar(hnew, "CDELT2", cdelt3, comment="DEGREES")
        sxaddpar(hnew, "CTYPE2", ctype3)
        sxaddpar(hnew, "NAXIS", 2)
        sxaddpar(hnew, "NAXIS1", nx)
        sxaddpar(hnew, "NAXIS2", ny)
        sxaddpar(hnew, "NAXIS3", 1)
        sxaddpar(hnew, "NAXIS4", 1)

        if chan:
            vorc = 'CHANNEL'
        else:
            vorc = 'VELOCITY'

        sxaddhist(hnew,
                  "WINDOW : %s; Window %s LIMITS" % (repr(windows), vorc))
        #sxaddpar(hnew, "BUNIT", units, "Units")
        sxdelpar(hnew, "CRVAL3")
        sxdelpar(hnew, "CRPIX3")
        sxdelpar(hnew, "CDELT3")
        sxdelpar(hnew, "CTYPE3")
        sxdelpar(hnew, "NAXIS3")
        sxdelpar(hnew, "NAXIS4")

        hdu_rms = pyfits.hdu.image.PrimaryHDU(data=sigma, header=hnew)
        return (hdu_orig, hdu_rms)
    else:
        return hdu_orig
Beispiel #5
0
def mkrmsimage(hdu,
               window,
               header=None,
               chan=False,
               dontblank=False,
               kms=True,
               moment=0):
    """
    Create rms image from spectral cube. The input cube is expected
    to be in the VLM format

    @param hdu: input pyfits style HDU (header data unit) or just the numpy
        numpy format data cube from pyfits HDU data attribute.
        This cube is expected to be in vlm format. If numpy format
        data cube is passed, then the header parameter should also be
        passed in.
    @type hdu: pyfits HDU or numpy array
    @param header: pyfits style header object that corresponds to the
        hdu data variable. This header parameter is only considered if
        the hdu parameter is a numpy array type rather than a pyfits HDU
        type
    @type header: pyfits header object
    @param window: list of tuples (pairs) of channels/velocity to exclude
        from polynomial calculation in determining rms. If chan is set to
        True, these should be integers. If chan is False, this is expected to be
        velocity expressed in kms (if the input parameter kms is True). If
        chan is False, and kms is False, v1 is treated with the same
        units as the FITS header describes.
    @param chan: If True, window variables are treated as channels. If False,
        they are treated as velocity
    @type chan: Boolean
    @param dontblank: By default, mkrmsimage will use the BLANK fits
        header value and automatically zero blanked values in order
        to compute rms. If dontblank keyword is set, then
        such blanking is not performed.
    @type dontblank: Boolean
    @param kms: If True velocity units is in kms.
    @type kms: Boolean
    @return: A HDU instance with 2d output map in the data attribute of the HDU, 
        and the corresponding header in header attribute of the HDU.

    """
    if isinstance(hdu, astropy.io.fits.hdu.image.PrimaryHDU):
        #get data and header from the hdu
        data = hdu.data
        header = hdu.header
    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header,
                                            astropy.io.fits.header.Header):
            raise SculptArgumentError(
                'header',
                "Since you passed in data that is a numpy array, set header to a pyfits header type"
            )
        data = hdu
    else:
        raise SculptArgumentError(
            'hdu',
            "can only be one of pyfits.PrimaryHDU type or numpy ndarray")
    #check for list or tuple type of window
    if type(window) not in (types.ListType, types.TupleType):
        raise SculptArgumentError('window',
                                  'has to be a List Type or Tuple Type')
    # calculate the x-axis (velocity)
    crpix1 = sxpar(header, "CRPIX1")
    crval1 = sxpar(header, "CRVAL1")
    cdelt1 = sxpar(header, "CDELT1")
    if kms:
        #convert velocity to km/s
        crval1 = crval1 / 1000.
        cdelt1 = cdelt1 / 1000.
    ctype1 = sxpar(header, "CTYPE1")
    crpix2 = sxpar(header, "CRPIX2")
    crval2 = sxpar(header, "CRVAL2")
    cdelt2 = sxpar(header, "CDELT2")
    ctype2 = sxpar(header, "CTYPE2")
    crpix3 = sxpar(header, "CRPIX3")
    crval3 = sxpar(header, "CRVAL3")
    cdelt3 = sxpar(header, "CDELT3")
    ctype3 = sxpar(header, "CTYPE3")
    nv = sxpar(header, "NAXIS1")
    nx = sxpar(header, "NAXIS2")
    ny = sxpar(header, "NAXIS3")
    blank = sxpar(header, "BLANK")

    cube = data.copy()
    if not dontblank and blank is not None:
        ind = numpy.where(cube == blank)
        cube[ind] = 0.0

    #get velocity axis
    velax = getaxes(header, 1)
    indices = numpy.zeros(velax.shape, dtype=bool)
    for v1, v2 in window:
        if chan:
            indices[v1:v2] = True
        else:
            ind = numpy.logical_and(velax >= v1, velax <= v2)
            indices = numpy.logical_or(indices, ind)
    indices = numpy.logical_not(indices)  # for indices to include in std calc

    rms = cube[:, :, indices].std(axis=2)
    hnew = header.copy()

    sxaddpar(hnew, "CRVAL1", crval2, comment="DEGREES")
    sxaddpar(hnew, "CRPIX1", crpix2)
    sxaddpar(hnew, "CDELT1", cdelt2, comment="DEGREES")
    sxaddpar(hnew, "CTYPE1", ctype2)
    sxaddpar(hnew, "CRVAL2", crval3, comment="DEGREES")
    sxaddpar(hnew, "CRPIX2", crpix3)
    sxaddpar(hnew, "CDELT2", cdelt3, comment="DEGREES")
    sxaddpar(hnew, "CTYPE2", ctype3)
    sxaddpar(hnew, "NAXIS", 2)
    sxaddpar(hnew, "NAXIS1", nx)
    sxaddpar(hnew, "NAXIS2", ny)
    sxaddpar(hnew, "NAXIS3", 1)
    sxaddpar(hnew, "NAXIS4", 1)
    if chan:
        vorc = 'CHANNEL'
    else:
        vorc = 'VELOCITY'
    sxaddhist(hnew, "WINDOW : %s; Window %s LIMITS" % (repr(window), vorc))
    #sxaddpar(hnew, "BUNIT", units, "Units")
    sxdelpar(hnew, "CRVAL3")
    sxdelpar(hnew, "CRPIX3")
    sxdelpar(hnew, "CDELT3")
    sxdelpar(hnew, "CTYPE3")
    sxdelpar(hnew, "NAXIS3")
    sxdelpar(hnew, "NAXIS4")
    hdu = pyfits.PrimaryHDU(rms, header=hnew)
    return hdu
Beispiel #6
0
def cube_extract(hdu, vxy, header=None):
    """
    Given a 3-dimensionsal FITS format cube, returns a portion (sub-cube)
    of it.
    @param hdu: input pyfits style HDU (header data unit) or just the numpy
        numpy format data image from pyfits HDU data attribute.
        If numpy format data cube is passed, then the header parameter
        should also be passed in.
    @param vxy: list or numpy array with 6 parameters, first 2 are limits of
        1st axis, 2nd pair is limits of 2nd axis, and 3rd pair are limits of
        3rd axis. Using -1 as a limit implies that you can use the limiting pixel.
        For example vxy = [-1, -1, 40, 60, 40, 60] will extract the full range
        in 1st axis, but 40:60 each in 2nd and 3rd axis.
    @type vxy: list or numpy array
    @param header: pyfits header object if needed
    @return: A HDU instance with 3d output subcube in the data attribute of the HDU, 
        and the corresponding header in header attribute of the HDU.
        """
    if isinstance(hdu, astropy.io.fits.hdu.image.PrimaryHDU):
        #get data and header from the hdu
        data = hdu.data
        header = hdu.header
    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header,
                                            astropy.io.fits.header.Header):
            raise SculptArgumentError(
                'header',
                "Since you passed in data that is a numpy array, set header to a pyfits header type"
            )
        data = hdu
    else:
        raise SculptArgumentError(
            'hdu',
            "can only be one of pyfits.PrimaryHDU type or numpy ndarray")
    if len(vxy) != 6:
        raise SculptArgumentError('vxy', "has to be of length 6")
    hdr = header.copy()
    dt = data.copy()
    naxis1 = sxpar(hdr, 'naxis1')
    naxis2 = sxpar(hdr, 'naxis2')
    naxis3 = sxpar(hdr, 'naxis3')
    v1, v2 = vxy[0], vxy[1]
    if v1 < 0:
        v1 = 0
    if v2 > naxis1 or v2 < 0:
        v2 = naxis1
    x1, x2 = vxy[2], vxy[3]
    if x1 < 0:
        x1 = 0
    if x2 > naxis2 or x2 < 0:
        x2 = naxis2
    y1, y2 = vxy[4], vxy[5]
    if y1 < 0:
        y1 = 0
    if y2 > naxis3 or y2 < 0:
        y2 = naxis3
    dt = dt[y1:y2, x1:x2, v1:v2]
    ny, nx, nv = dt.shape
    cards = hdr.cards
    card = cards['NAXIS1']
    card.value = nv
    card = cards['NAXIS2']
    card.value = nx
    card = cards['NAXIS3']
    card.value = ny

    #calculate velocity axis
    crval1 = sxpar(hdr, 'crval1')
    cdelt1 = sxpar(hdr, 'cdelt1')
    crpix1 = sxpar(hdr, 'crpix1')
    v = crval1 + (v1 - crpix1) * cdelt1
    card = cards['CRVAL1']
    card.value = v

    #x-axis
    card = cards['CRPIX2']
    card.value = card.value - x1

    #y-axis
    card = cards['CRPIX3']
    card.value = card.value - y1
    return pyfits.PrimaryHDU(dt, header=hdr)
Beispiel #7
0
    def draw_box_and_sigma_average(self):
        x = [f[0] for f in self.box]
        y = [f[1] for f in self.box]
        x.sort()
        y.sort()
        ax = self._figure.get_axes()[0]
        ax.hlines(y, x[0], x[1], colors='w')
        ax.vlines(x, y[0], y[1], colors='w')
        self.refresh()
        avgfigure = mpl.figure()
        avgax = avgfigure.add_subplot(111)
        if self.blue_windows:
            b1, b2 = self.blue_windows
        else:
            raise SculptArgumentError(
                'draw_box_and_sigma_average',
                'You have to set blue windows to be able to do sigma averaged windows'
            )
        if self.red_windows:
            r1, r2 = self.red_windows
        else:
            raise SculptArgumentError(
                'draw_box_and_sigma_average',
                'You have to set red windows to be able to do sigma averaged windows'
            )

        for i, hdu in enumerate(self.extra_hdus):
            hdunew = cube_extract(hdu, [-1, -1, x[0], x[1], y[0], y[1]])
            vel = getaxes(hdu.header, 1)
            if self.blue:
                blue, brms = momentcube(hdunew,
                                        b1,
                                        b2,
                                        returnrms=True,
                                        window=self.rms_window)
            else:
                red, rrms = momentcube(hdunew,
                                       r1,
                                       r2,
                                       returnrms=True,
                                       window=self.rms_window)

            if self.blue:
                #blue-weighted
                yind, xind = numpy.where(
                    blue.data > self.sigma_crit * brms.data / numpy.sqrt(2))
                avgspec = hdunew.data[yind, xind, :].mean(axis=0)
                ax.plot(xind + x[0], yind + y[0], 'bx')
                avgax.plot(vel,
                           avgspec,
                           linestyle='steps-mid',
                           label='blue wt %s' % self._get_hdu_title(i))
            else:
                #red-weighted
                yind, xind = numpy.where(
                    red.data > self.sigma_crit * rrms.data / numpy.sqrt(2))
                avgspec = hdunew.data[yind, xind, :].mean(axis=0)
                ax.plot(xind + x[0], yind + y[0], 'rx')
                avgax.plot(vel,
                           avgspec,
                           linestyle='steps-mid',
                           label='red wt %s' % self._get_hdu_title(i))
        avgax.set_title("Average made from %s qualifying points" % len(xind))
        avgax.legend(loc='best')
        avgfigure.canvas.draw()
        self.refresh()
Beispiel #8
0
def extract_posvel_angle(hdu, p1, angle, header=None, gauss_width=2):
    """
    Given a hdu in vlm format, and one position (in pixel
    coordinates), and an angle, obtains a position velocity cut about
    that position with that angle, along that line
    Returns p-v image as a pyfits hdu unit.
    @param hdu: input pyfits style HDU (header data unit) or just the numpy
        numpy format data cube from pyfits HDU data attribute.
        If numpy format data cube is passed, then the header parameter
        should also be passed in. The cube is expected to be in vlm format.
    @type hdu: pyfits hdu type or numpy nd-array
    @param p1: (x, y) pixel location of position 1. The x,y position can be a
        two-tuple, a list of two elements, or numpy array of two elements
    @type p1: tuple, list or array of floats or ints
    @param angle: angle of PV cut with respect to X-axis in degrees
    @type angle: float
    @param header: pyfits header object if needed
    @gauss_width: the width of the gaussian kernel to use in weighting
        neighboring pixels with when extracting spectra
    @type gauss_width: int
    @return A HDU instance with 2d position-velocity image in the data
        attribute of the HDU, and the corresponding header in header
        attribute of the HDU.
    """
    if isinstance(hdu, astropy.io.fits.hdu.image.PrimaryHDU):
        #get data and header from the hdu
        data = hdu.data
        header = hdu.header
    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header, astropy.io.fits.header.Header):
            raise SculptArgumentError('header', "Since you passed in data that is a numpy array, set header to a pyfits header type")
        data = hdu
    else:
        raise SculptArgumentError('hdu', "can only be one of pyfits.PrimaryHDU type or numpy ndarray")
    hdr = header.copy()
    dt = data.copy()
    hdu = pyfits.PrimaryHDU(dt, header=hdr)
    if gauss_width <= 0 or type(gauss_width) != types.IntType:
        raise SculptArgumentError('gauss_width', "should be positive and non-zero integer")
    try:
        if len(p1) != 2:
            raise SculptArgumentError('positions', "Positions p1 and p2 should be 2-element tuples, lists or arrays")
    except:
        raise SculptArgumentError('positions', "Positions p1 and p2 should be 2-element tuples, lists or arrays")
    a, b = p1
    #x2, y2 = p2
    m = math.tan(math.radians(angle)) #slope of line
    xmin, ymin = 0, 0
    y1, x1, v1 = hdu.data.shape
    ymax = y1-1
    xmax = x1-1
    print "xylims: ", xmin, ymin, xmax, ymax
    # #check for x-limits first
    # xl = None
    # xh = None
    # if m > 0.0:
    #     #line sloped right of vertical
    #     yl = m*(xmin-a) + b
    # else:
    #     #line sloped left of vertical
    #     yl = m*(xmax-a) + b
    # if ymin <= yl and yl <= ymax:
    #     if m > 0.0:
    #         xl = xmin
    #     else:
    #         xl = xmax
    # if m > 0.0:
    #     yh = m*(xmax-a) + b
    # else:
    #     yh = m*(xmin-a) + b
    # print "yl, yh = ", yl, yh
    # if ymin <= yh and yh <= ymax:
    #     if m > 0.0:
    #         xh = xmax
    #     else:
    #         xh = xmin
    # if xl is None:
    #     yl = None
    #     if m > 0.0:
    #         xl = ((ymin-b)/m) + a
    #     else:
    #         xl = ((ymax-b)/m) + a
    #     if xmin <= xl and xl <= xmax:
    #         yl = ymin
    # if xh is None:
    #     yh = None
    #     if m > 0.0:
    #         xh = ((ymax-b)/m) + a
    #     else:
    #         xh = ((ymin-b)/m) + a
    #     if xmin <= xh and xh <= xmax:
    #         yh = ymax
    i1, i2 = line_rectangle_intersection(xmin, xmax, ymin, ymax, a, b, angle)
    xl,yl = i1
    xh,yh = i2
    print xl, xh, yl, yh
    d = math.sqrt((xl-xh)**2 + (yl-yh)**2.)
    posvel = numpy.zeros((int(d), dt.shape[2]), dtype='float')
    dist = numpy.arange(int(d))
    if xl <= xh:
        x = xl + numpy.sqrt(dist**2./(1+m**2.)) #2nd term is deltax
    else:
        x = xl - numpy.sqrt(dist**2./(1+m**2.)) #2nd term is deltax
    y = yl + m*(x-xl)
    for i in range(int(d)):
        posvel[i,:] = extract_spec(hdu, x[i], y[i],
                                   gauss_width=gauss_width).data
    r, d = xyad(header, a, b)
    sxaddpar(hdr, "CRVAL2", r)
    dmid = math.sqrt((xl-a)**2 + (yl-b)**2)
    sxaddpar(hdr, "CRPIX2", int(dmid))

    sxaddpar(hdr, "NAXIS", 2)
    sxdelpar(hdr, "NAXIS3")

    for name in ('CTYPE', 'CRVAL', 'CDELT', 'CRPIX'):
            sxdelpar(hdr, "%s3" % name)
    sxaddhist(hdr, "Extracted posvel image from (%.1f, %.1f) with angle %.2f with gauss_width=%s" % (a, b, angle, gauss_width))
    return pyfits.PrimaryHDU(posvel, header=hdr)
Beispiel #9
0
def extract_spec(hdu, x0, y0, header=None, gauss_width=2):
    """
    Given a hdu in vlm format, and a x0,y0 location (in pixel
    coordinates), obtains a gaussian-convolved spectra
    around x0, y0 with width gauss_width.
    Returns spectrum as a pyfits hdu unit as well.
    @param hdu: input pyfits style HDU (header data unit) or just the numpy
        numpy format data cube from pyfits HDU data attribute.
        If numpy format data cube is passed, then the header parameter
        should also be passed in. The cube is expected to be in vlm format.
    @type hdu: pyfits hdu type or numpy nd-array
    @param x0: x pixel location where spectrum will be centered
    @type x0: float or int
    @param y0: y pixel location where spectrum will be centered
    @type y0: float or int    
    @param header: pyfits header object if needed
    @gauss_width: the width of the gaussian kernel to use in weighting
        neighboring pixels with.
    @type gauss_width: int
    @return A HDU instance with 1d spectrum map in the data attribute of the HDU, 
        and the corresponding header in header attribute of the HDU.
    
    """
    if isinstance(hdu, astropy.io.fits.hdu.image.PrimaryHDU):
        #get data and header from the hdu
        data = hdu.data
        header = hdu.header
    elif isinstance(hdu, numpy.ndarray):
        if header is None or not isinstance(header,
                                            astropy.io.fits.header.Header):
            raise SculptArgumentError(
                'header',
                "Since you passed in data that is a numpy array, set header to a pyfits header type"
            )
        data = hdu
    else:
        raise SculptArgumentError(
            'hdu',
            "can only be one of pyfits.PrimaryHDU type or numpy ndarray")
    hdr = header.copy()
    dt = data.copy()
    if gauss_width <= 0 or type(gauss_width) != types.IntType:
        raise SculptArgumentError('gauss_width',
                                  "should be positive and non-zero integer")
    gk = gauss_kern(gauss_width)
    kernx, kerny = gk.shape
    ysize, xsize, vsize = dt.shape
    if x0 < 0 or x0 >= xsize:
        raise SculptArgumentError(
            'x0', "x0=%s is out of bounds of x-limits: (0, %d)" % (x0, xsize))
    if y0 < 0 or y0 >= ysize:
        raise SculptArgumentError(
            'y0', "y0=%s is out of bounds of y-limits: (0, %d)" % (y0, ysize))
    #print gk.shape
    xmin = int(round(x0)) - kernx / 2
    xmax = xmin + kernx
    if xmin < 0:
        xmin = 0
    if xmax >= xsize:
        xmax = xsize - 1
    ymin = int(round(y0)) - kerny / 2
    ymax = ymin + kerny
    if ymin < 0:
        ymin = 0
    if ymax >= ysize:
        ymax = ysize - 1
    specdata = numpy.zeros(vsize, dtype='float')
    #print "Gk = " , gk
    #print xmin, xmax, ymin, ymax
    #print gk.sum().shape
    if xmax - xmin != kernx or ymax - ymin != kerny:
        specdata = dt[y0, x0, :]
    else:
        for i in range(vsize):
            specdata[i] = (gk * dt[ymin:ymax, xmin:xmax, i]).sum() / gk.sum()

    sxaddpar(hdr, "NAXIS", 1)
    sxdelpar(hdr, "NAXIS2")
    sxdelpar(hdr, "NAXIS3")
    for i in range(2, 4):
        for name in ('CTYPE', 'CRVAL', 'CDELT', 'CRPIX'):
            sxdelpar(hdr, "%s%i" % (name, i))
    sxaddhist(
        hdr, "Extracted spectrum at (%s, %s) with gauss_width=%s" %
        (x0, y0, gauss_width))
    return pyfits.PrimaryHDU(specdata, header=hdr)