def getaxes(header, axis='all', kms=True): """ L{getaxes} returns the axis vector(s) listed in keyword axis. @param header: a pyfits header instance. This is derived from pyfits.getheader or from the hdu instance header attribute of a pyfits HDU @param axis: can be string 'all', in which case it returns all axes available in the header. Returned as a dictionary with keys equaling axis number and values equaling corresponding axis vector. axis can also be set to None, which is the same as 'all'. axis can also be set to an integer axis number or a list of integer axis numbers. @type axis: Boolean @param kms: If set to True (default), if it finds velocity axis (it finds this by looking for CTYPE starting with velo), it will automatically divide by 1000. to convert velocity from m/s to km/s. @type kms: Boolean @return: returns axis. If only a single axis is requested (based on the type of axis input), a single numpy array of axis is returned. Otherwise a dictionary with axis number as keys and numpy array of axis as dictionary values is returned. """ allaxes = False if type(axis) == types.StringType: if axis.lower() == 'all': allaxes = True else: print "axis can be 'all' or an integer or list of integers." return None if type(axis) == types.NoneType: allaxes = True if not allaxes: axes = [] if type(axis) in (types.ListType, types.TupleType): for ax in axis: axes.append(ax) elif type(axis) == types.IntType: axes.append(axis) else: print "axis can be 'all' or an integer or list of integers." return None if allaxes: naxis = sxpar(header, 'naxis') axes = range(1, naxis + 1) axdic = {} for ax in axes: axdic[ax] = getax(header, ax) if kms: if sxpar(header, 'CTYPE%d' % ax).lower().startswith('velo'): #velocity axis axdic[ax] = axdic[ax] / 1000. if len(axes) == 1: return axdic[axes[0]] else: return axdic
def getaxes(header, axis='all', kms=True): """ L{getaxes} returns the axis vector(s) listed in keyword axis. @param header: a pyfits header instance. This is derived from pyfits.getheader or from the hdu instance header attribute of a pyfits HDU @param axis: can be string 'all', in which case it returns all axes available in the header. Returned as a dictionary with keys equaling axis number and values equaling corresponding axis vector. axis can also be set to None, which is the same as 'all'. axis can also be set to an integer axis number or a list of integer axis numbers. @type axis: Boolean @param kms: If set to True (default), if it finds velocity axis (it finds this by looking for CTYPE starting with velo), it will automatically divide by 1000. to convert velocity from m/s to km/s. @type kms: Boolean @return: returns axis. If only a single axis is requested (based on the type of axis input), a single numpy array of axis is returned. Otherwise a dictionary with axis number as keys and numpy array of axis as dictionary values is returned. """ allaxes = False if type(axis) == types.StringType: if axis.lower() == 'all': allaxes = True else: print "axis can be 'all' or an integer or list of integers." return None if type(axis) == types.NoneType: allaxes = True if not allaxes: axes = [] if type(axis) in (types.ListType, types.TupleType): for ax in axis: axes.append(ax) elif type(axis) == types.IntType: axes.append(axis) else: print "axis can be 'all' or an integer or list of integers." return None if allaxes: naxis = sxpar(header, 'naxis') axes = range(1, naxis+1) axdic = {} for ax in axes: axdic[ax] = getax(header, ax) if kms: if sxpar(header, 'CTYPE%d' % ax).lower().startswith('velo'): #velocity axis axdic[ax] = axdic[ax]/1000. if len(axes) == 1: return axdic[axes[0]] else: return axdic
def getax(header, ax): """ helper function for getaxes """ crval = sxpar(header, 'CRVAL%d' % ax) crpix = sxpar(header, 'CRPIX%d' % ax) cdelt = sxpar(header, 'CDELT%d' % ax) naxis = sxpar(header, 'NAXIS%d' % ax) return crval + (numpy.arange(naxis) - (crpix-1)) * cdelt
def getax(header, ax): """ helper function for getaxes """ crval = sxpar(header, 'CRVAL%d' % ax) crpix = sxpar(header, 'CRPIX%d' % ax) cdelt = sxpar(header, 'CDELT%d' % ax) naxis = sxpar(header, 'NAXIS%d' % ax) return crval + (numpy.arange(naxis) - (crpix - 1)) * cdelt
def xyad_cosdec(header, x, y): """ Given header and x, y pixels returns ra and dec coordinates corresponding to that x and y. This corrects for the cosine(declination) term for large fields-of-view. @param header: A pyfits style header object @param x: x pixel location (assumes RA axis) @param y: y pixel location (assumes Dec axis) @return : A tuple of (ra, dec) in decimal degrees """ naxis = sxpar(header, 'NAXIS') for i in range(1, naxis+1): if "RA" in sxpar(header, 'CTYPE%d' % i): ra_axis = i if "DEC" in sxpar(header, 'CTYPE%d' % i): dec_axis = i crval1 = sxpar(header,'CRVAL%d' % ra_axis) crval2 = sxpar(header,'CRVAL%d' % dec_axis) cdelt1 = sxpar(header,'CDELT%d' % ra_axis) cdelt2 = sxpar(header,'CDELT%d' % dec_axis) crpix1 = sxpar(header,'CRPIX%d' % ra_axis) crpix2 = sxpar(header,'CRPIX%d' % dec_axis) dec = crval2 + (y - crpix2)*cdelt2 ra = crval1 + (x - crpix1)*cdelt1/numpy.cos(numpy.radians(dec)) return (ra, dec)
def ad_cdec_xy(header, a, d): """ Given header and ra, dec returns x and y pixel locations for that ra and dec. This is similar to L{adxy} except that it keeps track of the cosine(declination) term for large fields-of-view. @param header: A pyfits style header object @param a: RA in decimal degrees @param d: DEC in decimal degrees @return : A tuple of (x, y) pixel locations """ naxis = sxpar(header, 'NAXIS') for i in range(1, naxis + 1): if "RA" in sxpar(header, 'CTYPE%d' % i): ra_axis = i if "DEC" in sxpar(header, 'CTYPE%d' % i): dec_axis = i crval1 = sxpar(header, 'CRVAL%d' % ra_axis) crval2 = sxpar(header, 'CRVAL%d' % dec_axis) cdelt1 = sxpar(header, 'CDELT%d' % ra_axis) cdelt2 = sxpar(header, 'CDELT%d' % dec_axis) crpix1 = sxpar(header, 'CRPIX%d' % ra_axis) crpix2 = sxpar(header, 'CRPIX%d' % dec_axis) x = crpix1 + math.cos(math.radians(d)) * (a - crval1) / cdelt1 y = crpix2 + (d - crval2) / cdelt2 return (x, y)
def ad_cdec_xy(header, a, d): """ Given header and ra, dec returns x and y pixel locations for that ra and dec. This is similar to L{adxy} except that it keeps track of the cosine(declination) term for large fields-of-view. @param header: A pyfits style header object @param a: RA in decimal degrees @param d: DEC in decimal degrees @return : A tuple of (x, y) pixel locations """ naxis = sxpar(header, 'NAXIS') for i in range(1, naxis+1): if "RA" in sxpar(header, 'CTYPE%d' % i): ra_axis = i if "DEC" in sxpar(header, 'CTYPE%d' % i): dec_axis = i crval1 = sxpar(header,'CRVAL%d' % ra_axis) crval2 = sxpar(header,'CRVAL%d' % dec_axis) cdelt1 = sxpar(header,'CDELT%d' % ra_axis) cdelt2 = sxpar(header,'CDELT%d' % dec_axis) crpix1 = sxpar(header,'CRPIX%d' % ra_axis) crpix2 = sxpar(header,'CRPIX%d' % dec_axis) x = crpix1+math.cos(math.radians(d))*(a-crval1)/cdelt1 y = crpix2+(d-crval2)/cdelt2 return (x, y)
def xyad_cosdec(header, x, y): """ Given header and x, y pixels returns ra and dec coordinates corresponding to that x and y. This corrects for the cosine(declination) term for large fields-of-view. @param header: A pyfits style header object @param x: x pixel location (assumes RA axis) @param y: y pixel location (assumes Dec axis) @return : A tuple of (ra, dec) in decimal degrees """ naxis = sxpar(header, 'NAXIS') for i in range(1, naxis + 1): if "RA" in sxpar(header, 'CTYPE%d' % i): ra_axis = i if "DEC" in sxpar(header, 'CTYPE%d' % i): dec_axis = i crval1 = sxpar(header, 'CRVAL%d' % ra_axis) crval2 = sxpar(header, 'CRVAL%d' % dec_axis) cdelt1 = sxpar(header, 'CDELT%d' % ra_axis) cdelt2 = sxpar(header, 'CDELT%d' % dec_axis) crpix1 = sxpar(header, 'CRPIX%d' % ra_axis) crpix2 = sxpar(header, 'CRPIX%d' % dec_axis) dec = crval2 + (y - crpix2) * cdelt2 ra = crval1 + (x - crpix1) * cdelt1 / numpy.cos(numpy.radians(dec)) return (ra, dec)
def xyad(header, x, y): """ Given header and x, y pixels returns world coordinates corresponding to that x and y. @param header: A pyfits style header object @param x: x pixel location (assumes RA axis) @param y: y pixel location (assumes Dec axis) @return : A tuple of world coordinates in decimal degrees """ #naxis = sxpar(header, 'NAXIS') # for i in range(1, naxis+1): # if "RA" in sxpar(header, 'CTYPE%d' % i): # ra_axis = i # if "DEC" in sxpar(header, 'CTYPE%d' % i): # dec_axis = i ra_axis = 2 dec_axis = 3 crval1 = sxpar(header,'CRVAL%d' % ra_axis) crval2 = sxpar(header,'CRVAL%d' % dec_axis) cdelt1 = sxpar(header,'CDELT%d' % ra_axis) cdelt2 = sxpar(header,'CDELT%d' % dec_axis) crpix1 = sxpar(header,'CRPIX%d' % ra_axis) crpix2 = sxpar(header,'CRPIX%d' % dec_axis) dec = crval2 + (y - crpix2)*cdelt2 ra = crval1 + (x - crpix1)*cdelt1 return (ra, dec)
def xyad(header, x, y): """ Given header and x, y pixels returns world coordinates corresponding to that x and y. @param header: A pyfits style header object @param x: x pixel location (assumes RA axis) @param y: y pixel location (assumes Dec axis) @return : A tuple of world coordinates in decimal degrees """ #naxis = sxpar(header, 'NAXIS') # for i in range(1, naxis+1): # if "RA" in sxpar(header, 'CTYPE%d' % i): # ra_axis = i # if "DEC" in sxpar(header, 'CTYPE%d' % i): # dec_axis = i ra_axis = 2 dec_axis = 3 crval1 = sxpar(header, 'CRVAL%d' % ra_axis) crval2 = sxpar(header, 'CRVAL%d' % dec_axis) cdelt1 = sxpar(header, 'CDELT%d' % ra_axis) cdelt2 = sxpar(header, 'CDELT%d' % dec_axis) crpix1 = sxpar(header, 'CRPIX%d' % ra_axis) crpix2 = sxpar(header, 'CRPIX%d' % dec_axis) dec = crval2 + (y - crpix2) * cdelt2 ra = crval1 + (x - crpix1) * cdelt1 return (ra, dec)
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
def fitsdir(directory=None, keywords=None, nosize=False, alt1_keywords=None, alt2_keywords=None, alt3_keywords=None, ext=0): """ The values of either user-specified or default FITS keywords are displayed in either the primary header and/or the first extension header. Unless nosize option is set to True, the data size is also displayed. The default keywords are as follows (with keywords in 2nd row used if those in the first row not found, and the 3rd row if neither the keywords in the first or second rows found:) DATE-OBS TELESCOP OBJECT EXPTIME TDATEOBS TELNAME TARGNAME INTEG #First Alternative DATE OBSERVAT EXPOSURE #Second Alternative INSTRUME EXPTIM #Third Alternative fitsdir will also recognize gzip compressed files (must have a .gz or FTZ extension). Example Usage: >>> fitsdir @param directory: Scalar string giving file name, disk or directory to be searched. Wildcard file names are allowed. If left blank, the current working directory is searched for FITS files. Examples of valid names include 'iraf/*.fits' (Unix). @type directory: string @param keywords: FITS keywords to display, as either a list or tuple of strings or as a comma delimited scalar string, e.g.'testname,dewar,filter'. If not supplied, then the default keywords are 'DATE-OBS', 'TELESCOP','OBJECT','EXPTIME' @type keywords: comma-delimited string or list or tuple of strings @param alt1_keywords: A list (either a list or tuple of strings) or a comma delimited strings of alternative keywords to use if the default keywords cannot be found. By default, 'TDATEOBS', is the alternative to DATE-OBS, 'TELNAME' for 'TELESCOP','TARGNAME' for 'OBJECT', and 'INTEG' for EXPTIME @type alt1_keywords: comma-delimited string or list or tuple of strings @param alt2_keywords: A list (either a list or tuple of strings) or a comma delimited strings of alternative keywords to use if neither keywords nor alt1_keywords can be found. @type alt2_keywords: comma-delimited string or list or tuple of strings @param alt3_keywords: A list (either a list or tuple of strings) or a comma delimited strings of alternative keywords to use if neither keywords nor alt1_keywords nor alt2_keywords can be found. @type alt3_keywords: comma-delimited string or list or tuple of strings @param nosize: if set to True, then information about the image size is not displayed @type nosize: Boolean @param ext: extension number to get. Default 0 @type ext: Integer """ if directory is None: directory = '*.fits*' dirlist = glob.glob(directory) keywords = _get_default_keywords( keywords, ['date-obs', 'telescop', 'object', 'exptime']) alt1_keywords = _get_default_keywords( alt1_keywords, ['tdateobs', 'telname', 'targname', 'integ']) alt2_keywords = _get_default_keywords(alt2_keywords, ['date', 'observat', '', 'exposure']) alt3_keywords = _get_default_keywords(alt3_keywords, ['', 'instrume', '', 'exptim']) if nosize: print "Filename\t " + '\t '.join(keywords) else: print "Filename\t Size\t " + '\t '.join(keywords) for fname in dirlist: header = pyfits.getheader(fname, ext=ext) sz = sxpar(header, 'naxis*') sizeint = [] for i in range(1, sz['NAXIS'] + 1): sizeint.append("%d" % sz['NAXIS%d' % i]) size = ' x '.join(sizeint) keyvalues = [] for i, kw in enumerate(keywords): if header.has_key(kw): keyvalues.append("%s" % sxpar(header, kw)) elif header.has_key(alt1_keywords[i]): keyvalues.append("%s" % sxpar(header, alt1_keywords[i])) elif header.has_key(alt2_keywords[i]): keyvalues.append("%s" % sxpar(header, alt2_keywords[i])) elif header.has_key(alt3_keywords[i]): keyvalues.append("%s" % sxpar(header, alt3_keywords[i])) else: keyvalues.append('None') if nosize: print "%s\t " % fname + '\t '.join(keyvalues) else: print "%s\t %s\t " % (fname, size) + '\t '.join(keyvalues)
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
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
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
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)
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)
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
def fitsdir(directory=None, keywords=None, nosize=False, alt1_keywords=None, alt2_keywords=None, alt3_keywords=None, ext=0): """ The values of either user-specified or default FITS keywords are displayed in either the primary header and/or the first extension header. Unless nosize option is set to True, the data size is also displayed. The default keywords are as follows (with keywords in 2nd row used if those in the first row not found, and the 3rd row if neither the keywords in the first or second rows found:) DATE-OBS TELESCOP OBJECT EXPTIME TDATEOBS TELNAME TARGNAME INTEG #First Alternative DATE OBSERVAT EXPOSURE #Second Alternative INSTRUME EXPTIM #Third Alternative fitsdir will also recognize gzip compressed files (must have a .gz or FTZ extension). Example Usage: >>> fitsdir @param directory: Scalar string giving file name, disk or directory to be searched. Wildcard file names are allowed. If left blank, the current working directory is searched for FITS files. Examples of valid names include 'iraf/*.fits' (Unix). @type directory: string @param keywords: FITS keywords to display, as either a list or tuple of strings or as a comma delimited scalar string, e.g.'testname,dewar,filter'. If not supplied, then the default keywords are 'DATE-OBS', 'TELESCOP','OBJECT','EXPTIME' @type keywords: comma-delimited string or list or tuple of strings @param alt1_keywords: A list (either a list or tuple of strings) or a comma delimited strings of alternative keywords to use if the default keywords cannot be found. By default, 'TDATEOBS', is the alternative to DATE-OBS, 'TELNAME' for 'TELESCOP','TARGNAME' for 'OBJECT', and 'INTEG' for EXPTIME @type alt1_keywords: comma-delimited string or list or tuple of strings @param alt2_keywords: A list (either a list or tuple of strings) or a comma delimited strings of alternative keywords to use if neither keywords nor alt1_keywords can be found. @type alt2_keywords: comma-delimited string or list or tuple of strings @param alt3_keywords: A list (either a list or tuple of strings) or a comma delimited strings of alternative keywords to use if neither keywords nor alt1_keywords nor alt2_keywords can be found. @type alt3_keywords: comma-delimited string or list or tuple of strings @param nosize: if set to True, then information about the image size is not displayed @type nosize: Boolean @param ext: extension number to get. Default 0 @type ext: Integer """ if directory is None: directory = '*.fits*' dirlist = glob.glob(directory) keywords = _get_default_keywords(keywords, ['date-obs','telescop','object','exptime']) alt1_keywords = _get_default_keywords(alt1_keywords, ['tdateobs','telname','targname','integ']) alt2_keywords = _get_default_keywords(alt2_keywords, ['date','observat','','exposure']) alt3_keywords = _get_default_keywords(alt3_keywords, ['','instrume','','exptim' ]) if nosize: print "Filename\t " + '\t '.join(keywords) else: print "Filename\t Size\t " + '\t '.join(keywords) for fname in dirlist: header = pyfits.getheader(fname, ext=ext) sz = sxpar(header, 'naxis*') sizeint = [] for i in range(1, sz['NAXIS']+1): sizeint.append("%d" % sz['NAXIS%d' % i]) size = ' x '.join(sizeint) keyvalues = [] for i, kw in enumerate(keywords): if header.has_key(kw): keyvalues.append("%s" % sxpar(header, kw)) elif header.has_key(alt1_keywords[i]): keyvalues.append("%s" % sxpar(header, alt1_keywords[i])) elif header.has_key(alt2_keywords[i]): keyvalues.append("%s" % sxpar(header, alt2_keywords[i])) elif header.has_key(alt3_keywords[i]): keyvalues.append("%s" % sxpar(header, alt3_keywords[i])) else: keyvalues.append('None') if nosize: print "%s\t " % fname + '\t '.join(keyvalues) else: print "%s\t %s\t " % (fname, size) + '\t '.join(keyvalues)