示例#1
0
def add_wcs_coordinates(objects, catParNames, catParFormt, catParUnits,
                        Parameters):
    try:
        hdulist = fits.open(Parameters["import"]["inFile"])
        header = hdulist[0].header
        hdulist.close()

        # Fix headers where "per second" is written "/S" instead of "/s"
        # (assuming they mean "per second" and not "per Siemens").
        if "cunit3" in header and "/S" in header["cunit3"]:
            err.warning("Converting '/S' to '/s' in CUNIT3.")
            header["cunit3"] = header["cunit3"].replace("/S", "/s")

        # Check if there is a Nmap/GIPSY FITS header keyword value present
        gipsyKey = [
            k for k in ["FREQ-OHEL", "FREQ-OLSR", "FREQ-RHEL", "FREQ-RLSR"]
            if (k in [header[key] for key in header if ("CTYPE" in key)])
        ]
        if gipsyKey:
            err.message(
                "GIPSY header found. Trying to convert to FITS standard.")
            from astropy.wcs import Wcsprm
            header = fix_gipsy_header(header)
            wcsin = Wcsprm(str(header))
            wcsin.sptr("VOPT-F2W")
            #if header["naxis"] == 4:
            #	objects = np.concatenate((objects, wcsin.p2s(np.concatenate((objects[:, catParNames.index("x"):catParNames. index("x") + 3], np.zeros((objects.shape[0], 1))), axis=1), 0)["world"][:,:-1]), axis=1)
            #else:
            #	objects = np.concatenate((objects, wcsin.p2s(objects[:, catParNames.index("x"):catParNames.index("x") + 3], 0)["world"]), axis=1)
            objects = np.concatenate(
                (objects,
                 wcsin.p2s(
                     objects[:,
                             catParNames.index("x"):catParNames.index("x") +
                             3], 0)["world"]),
                axis=1)
            catParUnits = tuple(
                list(catParUnits) +
                [str(cc).replace(" ", "") for cc in wcsin.cunit])
            catParNames = tuple(
                list(catParNames) + [(cc.split("--")[0]).lower()
                                     for cc in wcsin.ctype])
            catParFormt = tuple(
                list(catParFormt) + ["%15.7e", "%15.7e", "%15.7e"])

        else:
            # Constrain the RA axis reference value CRVAL_ to be between 0 and 360 deg
            rafound = 0
            for kk in range(header["naxis"]):
                if header["ctype1"][:2] == "RA":
                    rafound = 1
                    break
            if rafound:
                if header["crval%i" % (kk + 1)] < 0:
                    err.warning("Adding 360 deg to RA reference value.")
                    header["crval%i" % (kk + 1)] += 360
                elif header["crval%i" % (kk + 1)] > 360:
                    err.warning("Subtracting 360 deg from RA reference value.")
                    header["crval%i" % (kk + 1)] -= 360

            #if header["naxis"] == 4: wcsin = wcs.WCS(header, naxis=[wcs.WCSSUB_CELESTIAL, wcs.WCSSUB_SPECTRAL, wcs.WCSSUB_STOKES])
            #else: wcsin = wcs.WCS(header, naxis=[wcs.WCSSUB_CELESTIAL, wcs.WCSSUB_SPECTRAL])
            wcsin = wcs.WCS(header,
                            naxis=[wcs.WCSSUB_CELESTIAL, wcs.WCSSUB_SPECTRAL])
            xyz = objects[:,
                          catParNames.index("x"):catParNames.index("x") +
                          3].astype(float)
            if "cellscal" in header and header["cellscal"] == "1/F":
                err.warning(
                    "CELLSCAL keyword with value of 1/F found.\n"
                    "Will account for varying pixel scale in WCS coordinate calculation."
                )
                x0, y0 = header["crpix1"] - 1, header["crpix2"] - 1
                # Will calculate the pixscale factor of each channel as:
                # pixscale = ref_frequency / frequency
                if header["ctype3"] == "VELO-HEL":
                    pixscale = (1 - header["crval3"] / scipy.constants.c) / (
                        1 - (((xyz[:, 2] + 1) - header["crpix3"]) *
                             header["cdelt3"] + header["crval3"]) /
                        scipy.constants.c)
                else:
                    err.warning(
                        "Cannot convert 3rd axis coordinates to frequency. Ignoring the effect of CELLSCAL = 1/F."
                    )
                    pixscale = 1.0
                xyz[:, 0] = (xyz[:, 0] - x0) * pixscale + x0
                xyz[:, 1] = (xyz[:, 1] - y0) * pixscale + y0
            #if header["naxis"] == 4: objects = np.concatenate((objects, wcsin.wcs_pix2world(np.concatenate((xyz, np.zeros((objects.shape[0], 1))), axis=1), 0)[:, :-1]), axis=1)
            #else: objects = np.concatenate((objects, wcsin.wcs_pix2world(xyz, 0)), axis=1)
            objects = np.concatenate((objects, wcsin.wcs_pix2world(xyz, 0)),
                                     axis=1)
            catParUnits = tuple(
                list(catParUnits) +
                [str(cc).replace(" ", "") for cc in wcsin.wcs.cunit])
            catParNames = tuple(
                list(catParNames) + [(cc.split("--")[0]).lower()
                                     for cc in wcsin.wcs.ctype])
            catParFormt = tuple(
                list(catParFormt) + ["%15.7e", "%15.7e", "%15.7e"])
        #if header["naxis"] == 4:
        #	catParUnits = catParUnits[:-1]
        #	catParNames= catParNames[:-1]
        err.message("WCS coordinates added to catalogue.")

        # Create IAU-compliant source name:
        # WARNING: This currently assumes a regular, ≥ 2-dim. data cube where the first two axes are longitude and latitude.
        n_src = objects.shape[0]
        n_par = objects.shape[1]

        iau_names = np.empty([n_src, 1], dtype=object)

        if header["ctype1"][:4] == "RA--":
            # Equatorial coordinates; try to figure out equinox:
            iau_coord = "equ"
            if "equinox" in header:
                if int(header["equinox"]) >= 2000: iau_equinox = "J"
                else: iau_equinox = "B"
            elif "epoch" in header:
                # Assume that EPOCH has been abused to record the equinox:
                if int(header["epoch"]) >= 2000: iau_equinox = "J"
                else: iau_equinox = "B"
            else:
                # Equinox undefined:
                iau_equinox = "X"
        elif header["ctype1"][:4] == "GLON":
            # Galactic coordinates:
            iau_coord = "gal"
            iau_equinox = "G"
        else:
            # Unsupported coordinate system:
            iau_coord = ""
            iau_equinox = ""

        for src in xrange(n_src):
            lon = objects[src][n_par - 3]
            lat = objects[src][n_par - 2]

            if iau_coord == "equ":
                ra = Longitude(lon, unit=u.deg)
                dec = Latitude(lat, unit=u.deg)
                iau_pos = ra.to_string(unit=u.h,
                                       decimal=False,
                                       sep="",
                                       precision=2,
                                       alwayssign=False,
                                       pad=True,
                                       fields=3)
                iau_pos += dec.to_string(unit=u.deg,
                                         decimal=False,
                                         sep="",
                                         precision=1,
                                         alwayssign=True,
                                         pad=True,
                                         fields=3)
            else:
                iau_pos = "{0:08.4f}".format(lon)
                if lat < 0.0: iau_pos += "-"
                else: iau_pos += "+"
                iau_pos += "{0:07.4f}".format(abs(lat))

            iau_names[src][0] = "SoFiA " + iau_equinox + iau_pos

        objects = np.concatenate((objects, iau_names), axis=1)
        catParUnits = tuple(list(catParUnits) + ["-"])
        catParNames = tuple(list(catParNames) + ["name"])
        catParFormt = tuple(list(catParFormt) + ["%30s"])
    except:
        err.warning("WCS conversion of parameters failed.")

    return (objects, catParNames, catParFormt, catParUnits)
示例#2
0
def add_wcs_coordinates(objects, catParNames, catParFormt, catParUnits, Parameters):
	try:
		hdulist = fits.open(Parameters["import"]["inFile"])
		header = hdulist[0].header
		hdulist.close()
		
		# Fix headers where "per second" is written "/S" instead of "/s"
		# (assuming they mean "per second" and not "per Siemens").
		if "cunit3" in header and "/S" in header["cunit3"]:
			err.warning("Converting '/S' to '/s' in CUNIT3.")
			header["cunit3"] = header["cunit3"].replace("/S","/s")
		
		# Check if there is a Nmap/GIPSY FITS header keyword value present
		gipsyKey = [k for k in ["FREQ-OHEL", "FREQ-OLSR", "FREQ-RHEL", "FREQ-RLSR"] if (k in [header[key] for key in header if ("CTYPE" in key)])]
		if gipsyKey:
			err.message("GIPSY header found. Trying to convert to FITS standard.")
			from astropy.wcs import Wcsprm
			header = fix_gipsy_header(header)
			wcsin = Wcsprm(str(header))
			wcsin.sptr("VOPT-F2W")
			#if header["naxis"] == 4:
			#	objects = np.concatenate((objects, wcsin.p2s(np.concatenate((objects[:, catParNames.index("x"):catParNames. index("x") + 3], np.zeros((objects.shape[0], 1))), axis=1), 0)["world"][:,:-1]), axis=1)
			#else:
			#	objects = np.concatenate((objects, wcsin.p2s(objects[:, catParNames.index("x"):catParNames.index("x") + 3], 0)["world"]), axis=1)
			objects = np.concatenate((objects, wcsin.p2s(objects[:, catParNames.index("x"):catParNames.index("x") + 3], 0)["world"]), axis=1)
			catParUnits = tuple(list(catParUnits) + [str(cc).replace(" ", "") for cc in wcsin.cunit])
			catParNames = tuple(list(catParNames) + [(cc.split("--")[0]).lower() for cc in wcsin.ctype])
			catParFormt = tuple(list(catParFormt) + ["%15.7e", "%15.7e", "%15.7e"])
		
		else:
			# Constrain the RA axis reference value CRVAL_ to be between 0 and 360 deg
			rafound = 0
			for kk in range(header["naxis"]):
				if header["ctype1"][:2] == "RA":
					rafound = 1
					break
			if rafound:
				if header["crval%i" % (kk + 1)] < 0:
					err.warning("Adding 360 deg to RA reference value.")
					header["crval%i" % (kk + 1)] += 360
				elif header["crval%i" % (kk + 1)] > 360:
					err.warning("Subtracting 360 deg from RA reference value.")
					header["crval%i" % (kk + 1)] -= 360
			
			#if header["naxis"] == 4: wcsin = wcs.WCS(header, naxis=[wcs.WCSSUB_CELESTIAL, wcs.WCSSUB_SPECTRAL, wcs.WCSSUB_STOKES])
			#else: wcsin = wcs.WCS(header, naxis=[wcs.WCSSUB_CELESTIAL, wcs.WCSSUB_SPECTRAL])
			wcsin = wcs.WCS(header, naxis=[wcs.WCSSUB_CELESTIAL, wcs.WCSSUB_SPECTRAL])
			xyz = objects[:, catParNames.index("x"):catParNames.index("x") + 3].astype(float)
			if "cellscal" in header and header["cellscal"] == "1/F":
				err.warning(
					"CELLSCAL keyword with value of 1/F found.\n"
					"Will account for varying pixel scale in WCS coordinate calculation.")
				x0, y0 = header["crpix1"] - 1, header["crpix2"] - 1
				# Will calculate the pixscale factor of each channel as:
				# pixscale = ref_frequency / frequency
				if header["ctype3"] == "VELO-HEL":
					pixscale = (1 - header["crval3"] / scipy.constants.c) / (1 - (((xyz[:, 2] + 1) - header["crpix3"]) * header["cdelt3"] + header["crval3"]) / scipy.constants.c)
				else:
					err.warning("Cannot convert 3rd axis coordinates to frequency. Ignoring the effect of CELLSCAL = 1/F.")
					pixscale = 1.0
				xyz[:, 0] = (xyz[:, 0] - x0) * pixscale + x0
				xyz[:, 1] = (xyz[:, 1] - y0) * pixscale + y0
			#if header["naxis"] == 4: objects = np.concatenate((objects, wcsin.wcs_pix2world(np.concatenate((xyz, np.zeros((objects.shape[0], 1))), axis=1), 0)[:, :-1]), axis=1)
			#else: objects = np.concatenate((objects, wcsin.wcs_pix2world(xyz, 0)), axis=1)
			objects = np.concatenate((objects, wcsin.wcs_pix2world(xyz, 0)), axis=1)
			catParUnits = tuple(list(catParUnits) + [str(cc).replace(" ", "") for cc in wcsin.wcs.cunit])
			catParNames = tuple(list(catParNames) + [(cc.split("--")[0]).lower() for cc in wcsin.wcs.ctype])
			catParFormt = tuple(list(catParFormt) + ["%15.7e", "%15.7e", "%15.7e"])
		#if header["naxis"] == 4:
		#	catParUnits = catParUnits[:-1]
		#	catParNames= catParNames[:-1]
		err.message("WCS coordinates added to catalogue.")
		
		# Create IAU-compliant source name:
		# WARNING: This currently assumes a regular, ≥ 2-dim. data cube where the first two axes are longitude and latitude.
		n_src = objects.shape[0]
		n_par = objects.shape[1]
		
		iau_names = np.empty([n_src, 1], dtype=object)
		
		if header["ctype1"][:4] == "RA--":
			# Equatorial coordinates; try to figure out equinox:
			iau_coord = "equ"
			if "equinox" in header:
				if int(header["equinox"]) >= 2000: iau_equinox = "J"
				else: iau_equinox = "B"
			elif "epoch" in header:
				# Assume that EPOCH has been abused to record the equinox:
				if int(header["epoch"]) >= 2000: iau_equinox = "J"
				else: iau_equinox = "B"
			else:
				# Equinox undefined:
				iau_equinox = "X"
		elif header["ctype1"][:4] == "GLON":
			# Galactic coordinates:
			iau_coord = "gal"
			iau_equinox = "G"
		else:
			# Unsupported coordinate system:
			iau_coord = ""
			iau_equinox = ""
		
		for src in xrange(n_src):
			lon = objects[src][n_par - 3]
			lat = objects[src][n_par - 2]
			
			if iau_coord == "equ":
				ra = Longitude(lon, unit=u.deg)
				dec = Latitude(lat, unit=u.deg)
				iau_pos = ra.to_string(unit=u.h, decimal=False, sep="", precision=2, alwayssign=False, pad=True, fields=3)
				iau_pos += dec.to_string(unit=u.deg, decimal=False, sep="", precision=1, alwayssign=True, pad=True, fields=3)
			else:
				iau_pos = "{0:08.4f}".format(lon)
				if lat < 0.0: iau_pos += "-"
				else: iau_pos += "+"
				iau_pos += "{0:07.4f}".format(abs(lat))
			
			iau_names[src][0] = "SoFiA " + iau_equinox + iau_pos
		
		objects = np.concatenate((objects, iau_names), axis = 1)
		catParUnits = tuple(list(catParUnits) + ["-"])
		catParNames = tuple(list(catParNames) + ["name"])
		catParFormt = tuple(list(catParFormt) + ["%30s"])
	except:
		err.warning("WCS conversion of parameters failed.")
	
	return (objects, catParNames, catParFormt, catParUnits)
示例#3
0
 def displayText(self, value, locale):
     a = Latitude(value, u.deg)
     a.wrap_angle = 90 * u.deg
     value = str(
         a.to_string(unit=u.degree, precision=0, sep=("°", "'", "''")))
     return super(LatDelegate, self).displayText(value, locale)