def posang(l1, b1, l2, b2, system='galactic', units='degrees', **kwargs):
    """
    Return the position angle between two points assuming a rectilinear
    coordinate system (I think; at the very least I am making no corrections
    for wcs).

    INPUT:
    longitude1, latitude1, longitude2, latitude2

    Defaults to GALACTIC coordinates.  **kwargs are passed to coords.Position
    """
    pos1 = coords.Position([l1, b1], system=system, **kwargs)
    ra1, dec1 = pos1.j2000()
    pos2 = coords.Position([l2, b2], system=system, **kwargs)
    ra2, dec2 = pos2.j2000()

    radiff = (ra1 - ra2) / 180. * pi

    angle = arctan2(
        sin(radiff),
        cos(dec1 * pi / 180.) * tan(dec2 * pi / 180.) -
        sin(dec1 * pi / 180.) * cos(radiff))

    if units == 'degrees':
        return angle / pi * 180
    elif units == 'radians':
        return angle
    else:
        raise ValueError("Invalid units: %s" % units)
def coords_in_image(xc,yc,header,coordsys='celestial'):
    """
    Determine whether the coordinates are within the boundaries of the image
    """
    try:
        wcs = pywcs.WCS(header)
    except: # if the header isn't WCS compatible, we don't want it
        return False

    try:
        if coordsys=='celestial' and wcs.wcs.lngtyp=='GLON':
            xc,yc = coords.Position((xc,yc),system=coordsys).galactic()
        elif coordsys=='galactic' and wcs.wcs.lngtyp=='RA':
            xc,yc = coords.Position((xc,yc),system=coordsys).j2000()

        xp,yp = wcs.wcs_sky2pix(xc,yc,0)
    except:
        return False

    if xp > wcs.naxis1 or xp < 0:
        return False
    elif yp > wcs.naxis2 or yp < 0:
        return False
    else:
        return True
def gal2cel(regfile):
    """
    Converts a region file from galactic to celestial coordinates including
    position angle reference from the center of the box (right now only works
    on box regions)

    Requires pyregion with the ShapeList.write() function implemented...
    not clear if that exists in 1.0
    """
    reg = pyregion.open(regfile)

    for R in reg:
        if R.name == 'box':
            x, y, dx, dy, angle = R.coord_list

            posn = coords.Position([x, y], system='galactic')
            ra, dec = posn.j2000()

            newang = posang.posang(x - dx, y, x + dx, y, system='galactic')

            coord_list = [ra, dec, dx, dy, angle - newang - 90]

            R.coord_format = 'fk5'
            R.coord_list = coord_list
            R.params = coord_list

    reg.write(regfile[:-4] + "_fk5.reg")
示例#4
0
def coords_in_image(fitsfile,lon,lat,system='galactic'):
    """
    Determine whether the coordinates are inside the image
    """
    if not isinstance(fitsfile,pyfits.HDUList):
        fitsfile = pyfits.open(fitsfile)

    wcs = pywcs.WCS(flatten_header(fitsfile[0].header))

    if 'RA' in wcs.wcs.ctype[0]:
        pos = coords.Position((lon,lat),system=system)
        lon,lat = pos.j2000()
    if 'GLON' in wcs.wcs.ctype[0]:
        pos = coords.Position((lon,lat),system=system)
        lon,lat = pos.galactic()

    x,y = wcs.wcs_sky2pix(lon,lat,0)
    #DEBUG print x,y,wcs.naxis1,wcs.naxis2
    if (0 < x < wcs.naxis1) and (0 < y < wcs.naxis2):
        return True
    else:
        return False
def output_tab_delineated_spreadsheet(spreadsheet, print_column_headers=False):

    column_headers = [
        key for key in match_table.columns.keys if 'index' not in key
    ]

    primary_header = column_headers[0]

    column_headers.insert(1, 'DEC')
    column_headers.insert(1, 'RA')

    row_strings = []

    if print_column_headers:
        row_strings.append('\t'.join(column_headers))

    spreadsheet_matched = match_table.where(
        np.in1d(match_table[primary_header],
                spreadsheet[primary_header.lstrip('WUVARS_2014_')]))

    RA_array = []
    DEC_array = []

    for (ra, dec) in zip(spreadsheet.RA, spreadsheet.DEC):
        pp = coords.Position((ra, dec), units='rad')
        ra_s, de_s = pp.hmsdms().split(' ')
        RA_array.append(ra_s[:-1])
        DEC_array.append(' ' + de_s[:-2])

    for i in range(len(spreadsheet_matched)):

        row_list = [str(spreadsheet_matched[primary_header][i])]
        row_list.extend([str(RA_array[i]), str(DEC_array[i])])
        row_list.extend([
            str(spreadsheet_matched[header][i]) for header in column_headers
            if (header != primary_header) and (len(header) > 3)
        ])

        row_strings.append('\t'.join(row_list))

    return_string = '\n'.join(row_strings)

    return return_string
示例#6
0
    def rotcrop_cube(x1, y1, x2, y2, cubename, outname, xwidth=25, ywidth=25,
            in_system='galactic',  out_system='equatorial', clobber=True, 
            newheader=None, xcen=None, ycen=None):
        """
        Crop a data cube and then rotate it with montage

        """

        cubefile = pyfits.open(cubename)

        if xcen is None and ycen is None:
            pos1 = coords.Position([x1,y1],system=in_system)
            pos2 = coords.Position([x2,y2],system=in_system)

            if cubefile[0].header.get('CTYPE1')[:2] == 'RA':
                x1,y1 = pos1.j2000()
                x2,y2 = pos2.j2000()
                coord_system = 'celestial'
            elif  cubefile[0].header.get('CTYPE1')[:4] == 'GLON':
                x1,y1 = pos1.galactic()
                x2,y2 = pos2.galactic()
                coord_system = 'galactic'

            xcen = (x1+x2)/2.0
            ycen = (y1+y2)/2.0
            print xcen,ycen,xwidth,ywidth,coord_system
        else:
            coord_system = in_system

        sc = subcube(cubefile[0].data, xcen, xwidth, ycen, ywidth, 
                widthunits='pixels', units="wcs", header=cubefile[0].header,
                return_HDU=True)
        # note: there should be no security risk here because pyfits' writeto
        # will not overwrite by default
        tempcube = tempfile.mktemp(suffix='.fits')
        sc.writeto(tempcube)
        
        pa = posang.posang(x1,y1,x2,y2,system=coord_system) - 90

        if newheader is None:
            newheader = sc.header.copy()
            cd11 = newheader.get('CDELT1') if newheader.get('CDELT1') else newheader.get('CD1_1')
            cd22 = newheader.get('CDELT2') if newheader.get('CDELT2') else newheader.get('CD2_2')
            cd12 = newheader.get('CD1_2') if newheader.get('CD1_2') else 0.0
            cd21 = newheader.get('CD2_1') if newheader.get('CD2_1') else 0.0
            cdelt = numpy.sqrt(cd11**2+cd12**2)

            tempheader = tempfile.mktemp(suffix='.hdr')
            ycensign = "+" if numpy.sign(ycen) >= 0 else "-"
            montage.mHdr("%s %1s%s" % (xcen, ycensign, numpy.abs(ycen)), xwidth*cdelt,
                    tempheader, system=out_system, height=ywidth*cdelt,
                    pix_size=cdelt*3600.0, rotation=pa)
            os.system("sed -i bck '/END/d' %s" % (tempheader))
            newheader2 = pyfits.Header()
            newheader2.fromTxtFile(tempheader)
            #newheader2.fromtextfile(tempheader)
            for key in ('CRPIX3','CRVAL3','CDELT3','CD3_3','CUNIT3','WCSTYPE3','CTYPE3'):
                if newheader.get(key):
                    newheader2.update(key,newheader.get(key))
            if newheader.get('CD3_3') and newheader2.get('CDELT3') is None:
                newheader2.update('CDELT3',newheader.get('CD3_3'))
            newheader2.toTxtFile(tempheader,clobber=True)
            #if newheader2.get('CDELT3') is None:
            #    raise Exception("No CD3_3 or CDELT3 in header.")
        else:
            if isinstance(newheader,str):
                newheader2 = pyfits.Header()
                newheader2.fromTxtFile(newheader)
            tempheader = tempfile.mktemp(suffix='.hdr')
            newheader2.toTxtFile(tempheader,clobber=True)


        montage.wrappers.reproject_cube(tempcube,outname,header=tempheader,clobber=clobber)
        #print "\n",outname
        #os.system('imhead %s | grep CDELT' % outname)

        # AWFUL hack because montage removes CDELT3
        tempcube = pyfits.open(outname)
        tempcube.header = newheader2
        #if tempcube.header.get('CDELT3') is None:
        #    raise Exception("No CD3_3 or CDELT3 in header.")
        #print tempcube.header.get('CDELT3')
        tempcube.writeto(outname,clobber=True)
        #print tempcube.get('CDELT3')
        #print "\n",outname
        #os.system('imhead %s | grep CDELT' % outname)

        #print "\nnewheader2"
        #print newheader2.ascard
        #print
        
        return
示例#7
0
def aper_world2pix(ap,wcs,coordsys='galactic',wunit='arcsec'):
    """
    Converts an elliptical aperture (x,y,width,height,PA) from
    WCS to pixel coordinates given an input wcs (an instance
    of the pywcs.WCS class).  Must be a 2D WCS header.


    """
    convopt = {'arcsec':3600,'arcmin':60,'degree':1}
    try:
        conv = convopt[wunit]
    except:
        raise Exception("Must specify wunit='arcsec','arcmin', or 'degree'")

    if len(wcs.wcs.cdelt) != 2:
        raise Exception("WCS header is not strictly 2-dimensional.  Look for 3D keywords.")
    if '' in wcs.wcs.ctype:
        raise Exception("WCS header has no CTYPE.")
    pos = coords.Position((ap[0],ap[1]),system=coordsys)
    if wcs.wcs.ctype[0][:2] == 'RA':
        ra,dec = pos.j2000()
        corrfactor = cos(dec*dtor)
    elif wcs.wcs.ctype[0][:4] == 'GLON':
        ra,dec = pos.galactic()
        corrfactor=1
    else:
        raise Exception("WCS CTYPE has no match.")
    # workaround for a broken wcs.wcs_sky2pix
    try:
        radif = (wcs.wcs.crval[0]-ra)*dtor
        gamma = acos(cos(dec*dtor)*cos(wcs.wcs.crval[1]*dtor)*cos(radif)+sin(dec*dtor)*sin(wcs.wcs.crval[1]*dtor)) / dtor
        theta = atan2( sin(radif) , ( tan(dec*dtor)*cos(wcs.wcs.crval[1]*dtor)-sin(wcs.wcs.crval[1]*dtor)*cos(radif) ) )
        x = -gamma * sin(theta) / wcs.wcs.cd[0,0] + wcs.wcs.crpix[0]
        y = gamma * cos(theta) / wcs.wcs.cd[1,1] + wcs.wcs.crpix[1]
    except:
        radif = (wcs.wcs.crval[0]-ra)*dtor
        gamma = acos(cos(dec*dtor)*cos(wcs.wcs.crval[1]*dtor)*cos(radif)+sin(dec*dtor)*sin(wcs.wcs.crval[1]*dtor)) / dtor
        theta = atan2( sin(radif) , ( tan(dec*dtor)*cos(wcs.wcs.crval[1]*dtor)-sin(wcs.wcs.crval[1]*dtor)*cos(radif) ) )
        x = -gamma * sin(theta) / wcs.wcs.cdelt[0] + wcs.wcs.crpix[0]
        y = gamma * cos(theta) / wcs.wcs.cdelt[1] + wcs.wcs.crpix[1]
    
    #print "DEBUG: x,y from math (vectors): ",x,y
    #x,y = wcs.wcs_sky2pix(ra,dec,0)  # convert WCS coordinate to pixel coordinate (0 is origin, do not use fits convention)
    #print "DEBUG: x,y from wcs: ",x,y
    try:
        x=x[0] - 1 # change from FITS to python convention
        y=y[0] - 1 # change from FITS to python convention
        #print "DEBUG: x,y from math: ",x,y
    except:
        pass
    # cd is default, cdelt is backup
    if len(ap) > 3:
        try:
            width  = ap[2] / conv / abs(wcs.wcs.cd[0,0])  # first is width, second is height in DS9 PA convention
            height = ap[3] / conv / abs(wcs.wcs.cd[0,0])
        except:
            width  = ap[2] / conv / abs(wcs.wcs.cdelt[0])  # first is width, second is height in DS9 PA convention
            height = ap[3] / conv / abs(wcs.wcs.cdelt[0])
        apold = copy.copy(ap)
        if len(ap) == 5:
            PA = ap[4] 
            ap = [x,y,width,height,PA]
        else:
            ap = [x,y,width,height]
    elif len(ap) == 3:
        try:
            width  = ap[2] / conv / abs(wcs.wcs.cd[0,0])  # first is width, second is height in DS9 PA convention
        except:
            width  = ap[2] / conv / abs(wcs.wcs.cdelt[0])  # first is width, second is height in DS9 PA convention
        apold = copy.copy(ap)
        ap = [x,y,width]

    return ap
示例#8
0
    pcd_ra = pc['m0']['value'] * 180 / np.pi
    if pcd_ra < 0:
        pcd_ra += 360
    ms.done()
    pcd = [pcd_ra, pcd_dec]
    return pcd


if __name__ == '__main__':

    import astrolib.coords as coords
    import pyfits

    # lens positions for RXJ0911, presumably we want to this to be the phase center of the data/input visibilities for Ripples!!!!
    p_list = [
        coords.Position("09:11:27.56447 05:50:54.302").j2000(),
        coords.Position("09:11:27.51420 05:50:54.967").j2000()
    ]

    fits_cube = pyfits.open('calibrated.LSRK_cont_R05.image.fits')
    header = fits_cube[0].header
    ra_px, dec_px = coord2pix(p_list, header)
    print "RA, Dec: "
    print zip(ra_px, dec_px)

    x_cen, y_cen = offset_from_phs(header, ra_px[0], dec_px[0])
    print("X, Y offset in px from ideal phase center: {:.2f}, {:.2f}").format(
        x_cen, y_cen)

    # for Ripples input
    get_PB_arcsec(header)
def cutout(filename, xc, yc, xw=25, yw=25, units='pixels', outfile=None,
        clobber=True, useMontage=False, coordsys='celestial', verbose=False):
    """
    Inputs:
        file  - .fits filename or pyfits HDUList (must be 2D)
        xc,yc - x and y coordinates in the fits files' coordinate system (CTYPE)
        xw,yw - x and y width (pixels or wcs)
        units - specify units to use: either pixels or wcs
        outfile - optional output file
    """

    if isinstance(filename,str):
        file = pyfits.open(filename)
        opened=True
    elif isinstance(filename,pyfits.HDUList):
        file = filename
        opened=False
    else:
        raise Exception("cutout: Input file is wrong type (string or HDUList are acceptable).")

    head = file[0].header.copy()

    if head['NAXIS'] > 2:
        raise DimensionError("Too many (%i) dimensions!" % head['NAXIS'])
    cd1 = head.get('CDELT1') if head.get('CDELT1') else head.get('CD1_1')
    cd2 = head.get('CDELT2') if head.get('CDELT2') else head.get('CD2_2')
    if cd1 is None or cd2 is None:
        raise Exception("Missing CD or CDELT keywords in header")
    wcs = pywcs.WCS(head)

    if units == 'wcs':
        if coordsys=='celestial' and wcs.wcs.lngtyp=='GLON':
            xc,yc = coords.Position((xc,yc),system=coordsys).galactic()
        elif coordsys=='galactic' and wcs.wcs.lngtyp=='RA':
            xc,yc = coords.Position((xc,yc),system=coordsys).j2000()

    if useMontage and CanUseMontage:
        head['CRVAL1'] = xc
        head['CRVAL2'] = yc
        if units == 'pixels':
            head['CRPIX1'] = xw
            head['CRPIX2'] = yw
            head['NAXIS1'] = int(xw*2)
            head['NAXIS2'] = int(yw*2)
        elif units == 'wcs':
            
            cdelt = numpy.sqrt(cd1**2+cd2**2)
            head['CRPIX1'] = xw   / cdelt
            head['CRPIX2'] = yw   / cdelt
            head['NAXIS1'] = int(xw*2 / cdelt)
            head['NAXIS2'] = int(yw*2 / cdelt)

        head.toTxtFile('temp_montage.hdr',clobber=True)
        newfile = montage.wrappers.reproject_hdu(file[0],header='temp_montage.hdr',exact_size=True)
        os.remove('temp_montage.hdr')
    else:

        xx,yy = wcs.wcs_sky2pix(xc,yc,0)

        if units=='pixels':
            xmin,xmax = numpy.max([0,xx-xw]),numpy.min([head['NAXIS1'],xx+xw])
            ymin,ymax = numpy.max([0,yy-yw]),numpy.min([head['NAXIS2'],yy+yw])
        elif units=='wcs':
            xmin,xmax = numpy.max([0,xx-xw/numpy.abs(cd1)]),numpy.min([head['NAXIS1'],xx+xw/numpy.abs(cd1)])
            ymin,ymax = numpy.max([0,yy-yw/numpy.abs(cd2)]),numpy.min([head['NAXIS2'],yy+yw/numpy.abs(cd2)])
        else:
            raise Exception("Can't use units %s." % units)

        if xmax < 0 or ymax < 0:
            raise ValueError("Max Coordinate is outside of map: %f,%f." % (xmax,ymax))
        if ymin >= head.get('NAXIS2') or xmin >= head.get('NAXIS1'):
            raise ValueError("Min Coordinate is outside of map: %f,%f." % (xmin,ymin))

        head['CRPIX1']-=xmin
        head['CRPIX2']-=ymin
        head['NAXIS1']=int(xmax-xmin)
        head['NAXIS2']=int(ymax-ymin)

        if head.get('NAXIS1') == 0 or head.get('NAXIS2') == 0:
            raise ValueError("Map has a 0 dimension: %i,%i." % (head.get('NAXIS1'),head.get('NAXIS2')))

        img = file[0].data[ymin:ymax,xmin:xmax]
        newfile = pyfits.PrimaryHDU(data=img,header=head)
        if verbose: print "Cut image %s with dims %s to %s.  xrange: %f:%f, yrange: %f:%f" % (filename, file[0].data.shape,img.shape,xmin,xmax,ymin,ymax)

    if isinstance(outfile,str):
        newfile.writeto(outfile,clobber=clobber)

    if opened:
        file.close()

    return newfile
示例#10
0
def kdist(l, b, vin, near=True,r0=8.4e3,v0=2.54e2,dynamical=False,
        kinematic=True,regular=False,rrgal=False,verbose=False,
        inverse=False,silent=False, returnvtan=False):
    """
     NAME:
       KINDIST 
     PURPOSE:
       To return the distance to an object given l,b,v
    
     CALLING SEQUENCE:
       dist = KDIST (L, B, V)
    
     INPUTS:
       L, B -- Galactic Longitude and Latitude (decimal degrees)
       V - Velocity w.r.t. LSR in km/s
     KEYWORD PARAMETERS:
       /NEAR, /FAR -- Report the near/far kinematic distances for Q1 and
                      Q4 data.
       RO, VO -- Force values for galactocentric distance for sun and
                 velocity of the LSR around the GC.  Default to 8.4 kpc
                 and 254 km/s (Reid et al., 2009)
       RGAL -- Named keyword containing galactocentric radius of sources.
       rrgal  - return galactocentric distance in addition to distance from us
       /DYNAMICAL -- Use the dynamical definition of the LSR
       /KINEMATIC -- Use the kinematic definition of the LSR (default)
       /REGULAR -- Do not apply the rotation correction for High mass
                   star forming regions.
        INVERSE -- If set, pass DISTANCE instead of velocity, and output is
                   velocity
        returnvtan - if set, return the tanent velocity and ignore the input
                    velocity
     OUTPUTS:
       DIST -- the kinematic distance in units of R0 (defaults to pc).
    
     MODIFICATION HISTORY:
    
           Fri Feb 27 00:47:18 2009, Erik <*****@*****.**>
    		 Adapted from kindist.pro
                 Translated from IDL to Python by Adam Ginsburg ([email protected])

    """

    dtor = pi/180.

    if regular: vs = 0.0 
    else: vs=15.0

    if kinematic or not(dynamical):
        solarmotion_ra = ((18+03/6e1+50.29/3.6e3)*15)
        solarmotion_dec = (30+0/6e1+16.8/3.6e3)
        solarmotion_mag = 20.0
    else:
        solarmotion_ra = ((17+49/6e1+58.667/3.6e3)*15)
        solarmotion_dec = (28+7/6e1+3.96/3.6e3)
        solarmotion_mag = 16.55294

    cg = coords.Position((l,b),system='galactic')
    solarmotion = coords.Position((solarmotion_ra,solarmotion_dec))
    #  ra,dec = cg.j2000()
    #  gcirc, 2, solarmotion_ra, solarmotion_dec, ra, dec, theta
    theta = cg.angsep(solarmotion).arcsec()

    vhelio = vin-solarmotion_mag*cos(theta/206265.)

    # UVW from Dehnen and Binney
    bigu = 10.0
    bigv = 5.23
    bigw = 7.17

    v = vhelio+(bigu*cos(l*dtor)+bigv*sin(l*dtor))*cos(b*dtor)+bigw*sin(b*dtor)

    # Compute tangent distance and velocity
    rtan = r0*(cos(l*dtor))/(cos(b*dtor))
    vTEMP = (1/sin(l*dtor) - v0/(v0-vs)) * ((v0-vs)*sin(l*dtor)*cos(b*dtor))
    vhelioTEMP = vTEMP - ((bigu*cos(l*dtor)+bigv*sin(l*dtor))*cos(b*dtor)+bigw*sin(b*dtor))
    vtan = vhelioTEMP+solarmotion_mag*cos(theta/206265.)
    if returnvtan:
        return vtan

    # This is r/r0
    null = (v0/(v0-vs)+v/((v0-vs)*sin(l*dtor)*cos(b*dtor)))**(-1)

    if inverse:
        radical = cos(l*dtor) - cos(b*dtor) * vin / r0 
        null = sqrt(1 - cos(l*dtor)**2 + radical**2)
        v = (1/null - v0/(v0-vs)) * ((v0-vs)*sin(l*dtor)*cos(b*dtor))
        vhelio = v - ((bigu*cos(l*dtor)+bigv*sin(l*dtor))*cos(b*dtor)+bigw*sin(b*dtor))
        vlsr = vhelio+solarmotion_mag*cos(theta/206265.)
        return vlsr
    else:
        if vin > vtan:
            if not silent:
                print "Velocity is greater than tangent velocity v=%f.  Returning tangent distance." % vtan
            if rrgal: return rtan,null*r0
            return rtan
        #  The > 0 traps things near the tangent point and sets them to the
        #  tangent distance.  So quietly.  Perhaps this should pitch a flag?
        radical = max(sqrt(((cos(l*dtor))**2-(1-null**2)) ),0)

        fardist = r0*(cos(l*dtor)+radical)/(cos(b*dtor))

        neardist = r0*(cos(l*dtor)-radical)/(cos(b*dtor))

    rgal = null*r0
    ind = (abs(l-180) < 90)
    if ind.sum() > 1: neardist[ind] = fardist[ind]
    elif ind==True: neardist = fardist

    if not(near): dist = fardist
    else: dist = neardist

    if verbose:
        print "radical: %f  null: %f  vin: %f  v: %f  vhelio: %f rgal: %f  neardist: %f  fardist: %f" % (radical,null,vin,v,vhelio,rgal,neardist,fardist)

    if rrgal: return abs(dist),abs(rgal)
    return abs(dist)