Esempio n. 1
0
	def calculate(self):
		ephem_location = ephem.Observer()
		ephem_location.lat = self.location.latitude.to(u.rad) / u.rad
		ephem_location.lon = self.location.longitude.to(u.rad) / u.rad
		ephem_location.elevation = self.location.height / u.meter
		ephem_location.date = ephem.Date(self.time.datetime)

		if self.data is None:
			self.alt = Latitude([], unit=u.deg)
			self.az = Longitude([], unit=u.deg)
			self.names = Column([], dtype=np.str)
			self.vmag = Column([])
		else:
			ra = Longitude((self.data['RAh'], self.data['RAm'], self.data['RAs']), u.h)
			dec = Latitude((np.core.defchararray.add(self.data['DE-'], self.data['DEd'].astype(str)).astype(int), self.data['DEm'], self.data['DEs']), u.deg)
			c = SkyCoord(ra, dec, frame='icrs')
			altaz = c.transform_to(AltAz(obstime=self.time, location=self.location))
			self.alt = altaz.alt
			self.az = altaz.az

			self.names = self.data['Name']
			self.vmag = self.data['Vmag']

		for ephemeris in self.ephemerides:
			ephemeris.compute(ephem_location)
			self.vmag = self.vmag.insert(0, ephemeris.mag)
			self.alt = self.alt.insert(0, (ephemeris.alt.znorm * u.rad).to(u.deg))
			self.az = self.az.insert(0, (ephemeris.az * u.rad).to(u.deg))
			self.names = self.names.insert(0, ephemeris.name)
		
		return self.names, self.vmag, self.alt, self.az
Esempio n. 2
0
    def pixel_to_data(self, x, y, origin=0):
        """
        Convert a pixel coordinate to a data (world) coordinate by using
        `~astropy.wcs.WCS.wcs_pix2world`.

        Parameters
        ----------

        x : float
            Pixel coordinate of the CTYPE1 axis. (Normally solar-x).

        y : float
            Pixel coordinate of the CTYPE2 axis. (Normally solar-y).

        origin : int
            Origin of the top-left corner. i.e. count from 0 or 1.
            Normally, origin should be 0 when passing numpy indices, or 1 if
            passing values from FITS header or map attributes.
            See `~astropy.wcs.WCS.wcs_pix2world` for more information.

        Returns
        -------

        x : `~astropy.units.Quantity`
            Coordinate of the CTYPE1 axis. (Normally solar-x).

        y : `~astropy.units.Quantity`
            Coordinate of the CTYPE2 axis. (Normally solar-y).
        """
        x, y = self.wcs.wcs_pix2world(x, y, origin)

        # If the wcs is celestial it is output in degress
        if self.wcs.is_celestial:
            x *= u.deg
            y *= u.deg
        else:
            x *= self.units.x
            y *= self.units.y

        x = Longitude(x, wrap_angle=180 * u.deg)
        y = Latitude(y)

        return x.to(self.units.x), y.to(self.units.y)
Esempio n. 3
0
 def __init__(self, lon_0, lat_0, r_0):
     self.parameters = Parameters([
         Parameter('lon_0', Longitude(lon_0)),
         Parameter('lat_0', Latitude(lat_0)),
         Parameter('r_0', Angle(r_0))
     ])
Esempio n. 4
0
 def __init__(self, l, b, name=None):
     self['l'] = Longitude(l, wrap_angle=180. * u.degree)
     self['b'] = Latitude(b)
     self['name'] = name
Esempio n. 5
0
def read_manual_stars(filename):
    """
    Read in the stars manually measured from the chip and compute their expected alt and az coordinates.
    Return a numpy array with all the info.
    """

    lsst_location = EarthLocation(lat=-30.2444 * u.degree,
                                  lon=-70.7494 * u.degree,
                                  height=2650.0 * u.meter)

    names = ['star_name', 'x', 'y', 'mjd']
    types = ['|U10', float, float, float]

    obs_stars = np.loadtxt('starcoords.dat',
                           dtype=list(zip(names, types)),
                           skiprows=1,
                           delimiter=',')

    names.extend(['alt', 'az'])
    types.extend([float, float])

    new_cols = np.zeros(obs_stars.size, dtype=list(zip(names, types)))
    for name in obs_stars.dtype.names:
        new_cols[name] = obs_stars[name]

    obs_stars = new_cols

    ustars = np.unique(obs_stars['star_name'])
    names = ['star_name', 'ra', 'dec']
    types = ['|U20'] * 3
    star_coords = np.zeros(ustars.size, dtype=list(zip(names, types)))

    # Get the RA,Dec values for each star from Simbad
    for i, star_name in enumerate(ustars):
        result = Simbad.query_object(star_name)
        star_coords[i]['star_name'] = star_name
        ra = result['RA'][0].split(' ')
        ra = ra[0] + 'h' + ra[1] + 'm' + ra[2]
        star_coords[i]['ra'] = ra
        dec = result['DEC'][0].split(' ')
        dec = dec[0] + 'd' + dec[1] + 'm' + dec[2]
        star_coords[i]['dec'] = dec

    # Predict the alt, az values for each star at each MJD
    ra = Longitude(star_coords['ra'], unit=u.hourangle)
    dec = Latitude(star_coords['dec'], unit=u.deg)
    star_coords = SkyCoord(ra=ra, dec=dec, frame=ICRS)

    utimes = np.unique(obs_stars['mjd'])
    star_names = []
    mjds = []
    alts = []
    azs = []
    for time in utimes:
        time_mjd = Time(time, format='mjd')
        trans = star_coords.transform_to(
            AltAz(obstime=time_mjd, location=lsst_location))
        star_names.extend(ustars.tolist())
        mjds.extend([time] * ustars.size)
        alts.extend(trans.alt.value.tolist())
        azs.extend(trans.az.value.tolist())

    names = ['star_name', 'alt', 'az', 'mjd']
    types = ['|U10', float, float, float]

    predicted_array = np.zeros(len(azs), dtype=list(zip(names, types)))
    predicted_array['star_name'] = np.array(star_names)
    predicted_array['alt'] = np.array(alts)
    predicted_array['az'] = np.array(azs)
    predicted_array['mjd'] = np.array(mjds)

    predicted_array.sort(order=['star_name', 'mjd'])
    obs_stars.sort(order=['star_name', 'mjd'])
    hash1 = np.core.defchararray.add(obs_stars['star_name'],
                                     obs_stars['mjd'].astype('|U20'))
    hash2 = np.core.defchararray.add(predicted_array['star_name'],
                                     predicted_array['mjd'].astype('|U20'))

    good = np.in1d(hash2, hash1)
    predicted_array = predicted_array[good]
    obs_stars['alt'] = predicted_array['alt']
    obs_stars['az'] = predicted_array['az']

    return obs_stars
Esempio n. 6
0
def apparent_declination(t='now'):
    """Returns the apparent declination of the Sun."""
    ob = apparent_obliquity_of_ecliptic(t)
    app_long = apparent_longitude(t)
    result = np.degrees(np.arcsin(np.sin(ob)) * np.sin(app_long))
    return Latitude(result)
Esempio n. 7
0
class nullStation(lofasmStation):
    def __init__(self):
        '''
        empty lofasm station placeholder
        '''
        self.isNull = True
        lofasmStation.__init__(self, '', Latitude(0.0, 'deg'),
                               Longitude(0.0, 'deg'))

    def __repr__(self):
        return "<Null Station {}, lat {} lon {}>".format(
            self.name, self.lat.rad, self.lon.rad)

    def __str__(self):
        return self.__repr__()


station = {
    1:
    None,
    2:
    None,
    3:
    None,
    4:
    lofasmStation('LoFASM4', Latitude("35:14:50.0", "deg"),
                  Longitude("-116:47:35.77", "deg"), -10.42 * np.pi / 180, 748,
                  549.913767)
}
Esempio n. 8
0
def time_latitude():
    Latitude(3.2, u.degree)
Esempio n. 9
0
    assert f"'{c!s}' did not parse" in str(w[0].message)
    assert isinstance(cy, u.UnrecognizedUnit)
    assert str(cy) == str(c)

    with u.add_enabled_units(c):
        with catch_warnings() as w2:
            cy2 = load(s)
        assert len(w2) == 0

        assert cy2 is c


@pytest.mark.parametrize('c', [
    Angle('1 2 3', unit='deg'),
    Longitude('1 2 3', unit='deg'),
    Latitude('1 2 3', unit='deg'), [[1], [3]] * u.m,
    np.array([[1, 2], [3, 4]], order='F'),
    np.array([[1, 2], [3, 4]], order='C'),
    np.array([1, 2, 3, 4])[::2]
])
def test_ndarray_subclasses(c):
    cy = load(dump(c))

    assert np.all(c == cy)
    assert c.shape == cy.shape
    assert type(c) is type(cy)

    cc = 'C_CONTIGUOUS'
    fc = 'F_CONTIGUOUS'
    if c.flags[cc] or c.flags[fc]:
        assert c.flags[cc] == cy.flags[cc]
Esempio n. 10
0
 def lat(self):
     if self.lat_str[-1]=='s': m=-1.
     else: m=1.
     return m*Latitude(Angle(self.lat_str[:-1]))
Esempio n. 11
0
def latitudes(draw, min_lat: u.deg = -90 * u.deg, max_lat: u.deg = 90 * u.deg):
    lat = st.floats(min_value=min_lat.to_value(u.deg),
                    max_value=max_lat.to_value(u.deg),
                    allow_nan=False,
                    allow_infinity=False)
    return Latitude(draw(lat) * u.deg)
Esempio n. 12
0
def select_gladegalaxy_accordingto_location_radecpeakz(ra,
                                                       dec,
                                                       error,
                                                       peakz,
                                                       credzone=0.99,
                                                       nsigmas_in_d=3.0):

    prob = make_skymap_from_radec(ra, dec, error)

    print('Applying <', credzone, ' pos prob cut and ', nsigmas_in_d,
          ' sigma distance cut!')
    ####star here, it's the same for other triggers###
    # loading the galaxy catalog. this updated glade catalog including RA, DEC, distance, Bmag and ID
    galax = np.load(glade_RA_DEC_Dis_Bmag_ID)

    # map parameters:
    npix = len(prob)
    nside = hp.npix2nside(npix)

    # galaxy parameters(RA, DEC to theta, phi):
    galax = (galax[np.where(
        galax[:, 2] > 0), :])[0]  # filter out negative distance

    theta = 0.5 * np.pi - np.pi * (galax[:, 1]) / 180
    phi = np.deg2rad(galax[:, 0])
    d = np.array(galax[:, 2])

    # converting galaxy coordinates to map pixels:
    ipix = hp.ang2pix(nside, theta, phi)

    # finding given percent probability zone(default is 99%):
    probcutoff = 1
    probsum = 0
    npix99 = 0
    sortedprob = np.sort(prob)
    while probsum < credzone:
        probsum = probsum + sortedprob[-1]
        probcutoff = sortedprob[-1]
        sortedprob = sortedprob[:-1]
        npix99 = npix99 + 1
    area = npix99 * hp.nside2pixarea(nside, degrees=True)
    ####end here, it's the same for other triggers###
    ####################################################
    ####it's different below because it need to do distance cut

    # calculating probability for galaxies by the localization map:
    ppos = prob[ipix]
    distp = cal_distance_p_from_powerlaw(galax[:, 2], peakredshift=peakz)
    cutp = np.median(distp) * nsigmas_in_d * 0.3
    print('cutp is :', cutp)

    # cuttoffs- 99% of probability by angles and 3sigma by distance:
    inddistance = np.where(distp >= cutp)
    indcredzone = np.where(ppos >= probcutoff)
    print(len(indcredzone[0]), ' was selected according to location')
    print(len(inddistance[0]), ' was selected according to distance')

    ##at this step, we'll always do masscut
    #doMassCuttoff = True

    # if no galaxies
    if (galax[np.intersect1d(indcredzone, inddistance)]).size == 0:
        while probsum < 0.99995:
            if sortedprob.size == 0:
                break
            probsum = probsum + sortedprob[-1]
            probcutoff = sortedprob[-1]
            sortedprob = sortedprob[:-1]
            npix99 = npix99 + 1
        print('No galaxy select with default cut, prob<0.99, dis < 3 sigma')
        print('Loosing the pos prob cut to 0.99995')
        print('and loosing the dis prob cut to 5 sigma')
        cutp = np.median(distp) * 5.0 * 0.3
        inddistance = np.where(distp >= cutp)
        indcredzone = np.where(ppos >= probcutoff)
        ##at this step, we'll always do masscut
        #doMassCuttoff = False

    indselectedgala = np.intersect1d(indcredzone, inddistance)
    ipix = ipix[indselectedgala]
    ppos = ppos[indselectedgala]
    distp = distp[indselectedgala]
    Sloc = ppos * distp
    Sloc = Sloc / np.sum(Sloc)

    galax = galax[indselectedgala]
    if galax.size == 0:
        # print "no galaxies in field"
        # print "99.995% of probability is ", npix99*hp.nside2pixarea(nside, degrees=True), "deg^2"
        # print "peaking at [RA,DEC](deg) = ", maxprobcoord
        print('No galaxy was selected')
        return

    ##great, we have galaxy selected, need to return them as astropy.table format, add the score information
    galaxytable = Table(galax,
                        names=('raDeg', 'decDeg', 'disMpc', 'Bmag', 'gladeID'),
                        dtype=('f', 'f', 'f', 'f', 'i'))
    print(len(galaxytable), ' galaxies are selected!')
    ##add distance to center too
    dis = (SkyCoord(Longitude(galaxytable['raDeg'], unit=u.deg),
                    Latitude(galaxytable['decDeg'], unit=u.deg),
                    frame='icrs').separation(SkyCoord(
                        ra, dec, unit="deg"))).value * 60  ##degree to arcmin
    galaxytable.add_column(Column(dis, name='DisToCentre_Arcmin'))
    galaxytable.add_column(Column(Sloc, name='S_total'))
    galaxytable.add_column(Column(ppos, name='P_pos'))
    galaxytable.add_column(Column(distp, name='P_dis'))
    galaxytable.add_column(Column(Sloc, name='S_loc'))
    indextmp = np.argsort(galaxytable['S_total'])[::-1]
    galaxytable = galaxytable[indextmp]
    return galaxytable
Esempio n. 13
0
def select_gladegalaxy_accordingto_location_gw(gwskymap,
                                               credzone=0.99,
                                               nsigmas_in_d=3.0):
    try:
        skymap = hp.read_map(gwskymap, field=None, verbose=False)
    except Exception as e:
        print("Failed to read sky map file", gwskymap)
        return
    ##the skymap file from gw has both the location information and also the distance information
    if (isinstance(skymap, np.ndarray)
            or isinstance(skymap, tuple)) and len(skymap) == 4:
        prob, distmu, distsigma, distnorm = skymap
        # print('Yes distance information available. Can produce galaxy list.')
    else:
        print(
            'No distance information available. Cannot produce galaxy list. Check!'
        )
        return

    print('Applying <', credzone, ' pos prob cut and ', nsigmas_in_d,
          ' sigma distance cut!')
    ####star here, it's the same for other triggers###
    # loading the galaxy catalog. this updated glade catalog including RA, DEC, distance, Bmag and ID
    galax = np.load(glade_RA_DEC_Dis_Bmag_ID)

    # map parameters:
    npix = len(prob)
    nside = hp.npix2nside(npix)

    # galaxy parameters(RA, DEC to theta, phi):
    galax = (galax[np.where(
        galax[:, 2] > 0), :])[0]  # filter out negative distance

    theta = 0.5 * np.pi - np.pi * (galax[:, 1]) / 180
    phi = np.deg2rad(galax[:, 0])
    d = np.array(galax[:, 2])

    # converting galaxy coordinates to map pixels:
    ipix = hp.ang2pix(nside, theta, phi)

    # finding given percent probability zone(default is 99%):
    probcutoff = 1
    probsum = 0
    npix99 = 0
    sortedprob = np.sort(prob)
    while probsum < credzone:
        probsum = probsum + sortedprob[-1]
        probcutoff = sortedprob[-1]
        sortedprob = sortedprob[:-1]
        npix99 = npix99 + 1
    area = npix99 * hp.nside2pixarea(nside, degrees=True)
    ####end here, it's the same for other triggers###
    ####################################################
    ####it's different below because it need to do distance cut

    # calculating probability for galaxies by the localization map:
    ppos = prob[ipix]
    distp = (norm(distmu[ipix], distsigma[ipix]).pdf(d) * distnorm[ipix])
    # * d**2)#/(norm(distmu[ipix], distsigma[ipix]).pdf(distmu[ipix]) * distnorm[ipix] * distmu[ipix]**2)

    # cuttoffs- 99% of probability by angles and 3sigma by distance:
    inddistance = np.where(
        np.abs(d - distmu[ipix]) < nsigmas_in_d * distsigma[ipix])
    indcredzone = np.where(ppos >= probcutoff)
    print(len(indcredzone[0]), ' was selected according to location')
    print(len(inddistance[0]), ' was selected according to distance')

    ##at this step, we'll always do masscut
    #doMassCuttoff = True

    # if no galaxies
    if (galax[np.intersect1d(indcredzone, inddistance)]).size == 0:
        while probsum < 0.99995:
            if sortedprob.size == 0:
                break
            probsum = probsum + sortedprob[-1]
            probcutoff = sortedprob[-1]
            sortedprob = sortedprob[:-1]
            npix99 = npix99 + 1
        print('No galaxy select with default cut, prob<0.99, dis < 3 sigma')
        print('Loosing the pos prob cut to 0.99995')
        print('and loosing the dis prob cut to 5 sigma')
        inddistance = np.where(np.abs(d - distmu[ipix]) < 5 * distsigma[ipix])
        indcredzone = np.where(ppos >= probcutoff)
        ##at this step, we'll always do masscut
        #doMassCuttoff = False

    indselectedgala = np.intersect1d(indcredzone, inddistance)
    ipix = ipix[indselectedgala]
    ppos = ppos[indselectedgala]
    distp = distp[indselectedgala]
    Sloc = ppos * distp
    Sloc = Sloc / np.sum(Sloc)

    galax = galax[indselectedgala]
    if galax.size == 0:
        # print "no galaxies in field"
        # print "99.995% of probability is ", npix99*hp.nside2pixarea(nside, degrees=True), "deg^2"
        # print "peaking at [RA,DEC](deg) = ", maxprobcoord
        return

    ##great, we have galaxy selected, need to return them as astropy.table format, add the score information
    galaxytable = Table(galax,
                        names=('raDeg', 'decDeg', 'disMpc', 'Bmag', 'gladeID'),
                        dtype=('f', 'f', 'f', 'f', 'i'))
    print(len(galaxytable), ' galaxies are selected!')
    ##add distance to center too
    peakpid = np.argsort(prob)[-1]
    racent, deccent = hp.pix2ang(
        nside, peakpid,
        lonlat=True)  ##must give lonlat=True keywork to make result degree
    dis = (SkyCoord(Longitude(galaxytable['raDeg'], unit=u.deg),
                    Latitude(galaxytable['decDeg'], unit=u.deg),
                    frame='icrs').separation(
                        SkyCoord(racent, deccent,
                                 unit="deg"))).value * 60  ##degree to arcmin
    galaxytable.add_column(Column(dis, name='DisToCentre_Arcmin'))
    galaxytable.add_column(Column(Sloc, name='S_total'))
    galaxytable.add_column(Column(ppos, name='P_pos'))
    galaxytable.add_column(Column(distp, name='P_dis'))
    galaxytable.add_column(Column(Sloc, name='S_loc'))
    indextmp = np.argsort(galaxytable['S_total'])[::-1]
    galaxytable = galaxytable[indextmp]
    return galaxytable
Esempio n. 14
0
            cat_ic = nml_aa.transform_to(ICRS())
            # apparent AltAz (mnt), includes refraction etc.
            # only SOFA/ERFA built in refraction is supported
            #cat_ll_ap=cat_ic.transform_to(AltAz(pressure=args.pressure_qfe*u.hPa,temperature=args.temperature*u.deg_C,relative_humidity=args.humidity))
            # cat_ll_ap is either cat_aa or cat_ha
            cat_ll_ap = tr_t_tf(tf=cat_ic, sky=meteo_only_sky)
            if args.model_class in 'altaz':
                #
                # subtract the correction
                #                |
                #                |                                                     | 0. here
                vd_lon = Longitude(
                    -model.d_lon(cat_ll_ap.az.radian, cat_ll_ap.alt.radian,
                                 0.), u.radian)
                vd_lat = Latitude(
                    -model.d_lat(cat_ll_ap.az.radian, cat_ll_ap.alt.radian,
                                 0.), u.radian)
            else:
                vd_lon = Longitude(
                    -model.d_lon(cat_ll_ap.ra.radian, cat_ll_ap.dec.radian,
                                 0.), u.radian)
                vd_lat = Latitude(
                    -model.d_lat(cat_ll_ap.ra.radian, cat_ll_ap.dec.radian,
                                 0.), u.radian)

            for i in range(0, args.data_points):
                # noise
                if sigma != 0.:
                    vn_lon = Longitude(np.random.normal(loc=0., scale=sigma),
                                       u.radian)
                    vn_lat = Latitude(np.random.normal(loc=0., scale=sigma),
Esempio n. 15
0
    def from_geodetic(cls,
                      lon,
                      lat,
                      height=0.0,
                      ellipsoid=EARTH_ELLIPSOID_GRS80):
        """
        Location on Central Body (e.g. Earth or Moon), initialized from
        Central Body detic (e.g. geodetic for the Earth) coordinates.

        This is the same as `from_cb_detic` method. It is kept for compatibility with
        :class:`astropy.coordinates.EarthLocation` class.

        Parameters
        ----------
        lon : `~astropy.coordinates.Longitude` or float
            East longitude.  Can be anything that initialises an
            `~astropy.coordinates.Angle` object (if float, in degrees).
        lat : `~astropy.coordinates.Latitude` or float
            latitude.  Can be anything that initialises an
            `~astropy.coordinates.Latitude` object (if float, in degrees).
        height : `~astropy.units.Quantity` or float, optional
            Height above reference ellipsoid (if float, in meters; default: 0).
        ellipsoid : CelestialBodyEllipsoid, optional
            Definition of the reference ellipsoid to use
            (default: 'EARTH_ELLIPSOID_GRS80').


        Raises
        ------
        astropy.units.UnitsError
            If the units on ``lon`` and ``lat`` are inconsistent with angular
            ones, or that on ``height`` with a length.
        ValueError
            If ``lon``, ``lat``, and ``height`` do not have the same shape

        Notes
        -----
        For the conversion to geocentric coordinates, the ERFA routine
        ``gd2gce`` is used.  See https://github.com/liberfa/erfa
        """
        # We use Angle here since there is no need to wrap the longitude -
        # gd2gce will just take cos/sin anyway.  And wrapping might fail
        # on readonly input.
        lon = Angle(lon, u.degree, copy=False)
        lat = Latitude(lat, u.degree, copy=False)
        # don't convert to m by default, so we can use the height unit below.
        if not isinstance(height, u.Quantity):
            height = u.Quantity(height, u.m, copy=False)
        # get geocentric coordinates. Have to give one-dimensional array.
        xyz = erfa.gd2gce(
            ellipsoid.re.to_value(u.m),
            1 / ellipsoid.inv_f.to_value(),
            lon.to_value(u.radian),
            lat.to_value(u.radian),
            height.to_value(u.m),
        )
        self = xyz.ravel().view(cls._location_dtype,
                                cls).reshape(xyz.shape[:-1])
        self._unit = u.m
        self._ellipsoid = ellipsoid
        return self
Esempio n. 16
0
def nai_detector_radecs(detectors, scx, scz, time):
    """
    calculates the RA/DEC for each NaI detector given spacecraft z and x RA/DEC
    positions.

    NB: This routine is based on code found in GTBURST, originally written by
    Dr Giacamo Vianello for the Fermi Science Tools.

    Parameters
    ----------

    detectors : `dict`
        A dictionary containing the Fermi/GBM detector pointing angles relative
        to the spacecraft axes. Obtained from the nai_detector_angles function.
    scx : array-like
        Two-element tuple containing the RA/DEC information of the Fermi
        spacecraft X-axis
    scz : array-like
        Two-element tuple containing the RA/DEC information of the Fermi
        spacecraft Z-axis
    time : `datetime.datetime`
        The time corresponding to the input scx and scz values, in a format
        understandable by parse_time.

    Returns
    -------
    `dict`
        A dictionary containing the RA/DEC for each Fermi/GBM NaI detector at
        the given input time.
    """

    scx_vector = (np.array([
        np.cos(scx[0].to('rad').value) * np.cos(scx[1].to('rad').value),
        np.sin(scx[0].to('rad').value) * np.cos(scx[1].to('rad').value),
        np.sin(scx[1].to('rad').value)
    ]))

    scz_vector = (np.array([
        np.cos(scz[0].to('rad').value) * np.cos(scz[1].to('rad').value),
        np.sin(scz[0].to('rad').value) * np.cos(scz[1].to('rad').value),
        np.sin(scz[1].to('rad').value)
    ]))

    # For each detector, do the rotation depending on the detector zenith and
    # azimuth angles.
    detector_radecs = copy.deepcopy(detectors)
    for l, d in detectors.items():
        phi = d[0].value
        theta = d[1].value

        # rotate about spacecraft z-axis first
        vx_primed = rotate_vector(scx_vector, scz_vector, np.deg2rad(phi))

        # now find spacecraft y-axis using cross product
        vy_primed = np.cross(scz_vector, vx_primed)

        # do the second part of the rotation around vy
        vz_primed = rotate_vector(scz_vector, vy_primed, np.deg2rad(theta))

        # now we should be pointing at the new RA/DEC.
        ra = Longitude(
            np.degrees(np.arctan2(vz_primed[1], vz_primed[0])) * u.deg)
        dec = Latitude(np.degrees(np.arcsin(vz_primed[2])) * u.deg)

        # save the RA/DEC in a dictionary
        detector_radecs[l] = [ra, dec]

    detector_radecs['time'] = time
    return detector_radecs
Esempio n. 17
0
def healpix_to_lonlat(healpix_index, nside, dx=None, dy=None, order='ring'):
    """
    Convert HEALPix indices (optionally with offsets) to longitudes/latitudes.

    If no offsets (``dx`` and ``dy``) are provided, the coordinates will default
    to those at the center of the HEALPix pixels.

    Parameters
    ----------
    healpix_index : int or `~numpy.ndarray`
        HEALPix indices (as a scalar or array)
    nside : int
        Number of pixels along the side of each of the 12 top-level HEALPix tiles
    dx, dy : float or `~numpy.ndarray`, optional
        Offsets inside the HEALPix pixel, which must be in the range [0:1],
        where 0.5 is the center of the HEALPix pixels (as scalars or arrays)
    order : { 'nested' | 'ring' }, optional
        Order of HEALPix pixels

    Returns
    -------
    lon : :class:`~astropy.coordinates.Longitude`
        The longitude values
    lat : :class:`~astropy.coordinates.Latitude`
        The latitude values
    """

    if (dx is None and dy is not None) or (dx is not None and dy is None):
        raise ValueError('Either both or neither dx and dy must be specified')

    healpix_index = np.asarray(healpix_index, dtype=np.int64)

    if dx is None and dy is not None:
        dx = 0.5
    elif dx is not None and dy is None:
        dy = 0.5

    if dx is not None:
        dx = np.asarray(dx, dtype=np.float)
        dy = np.asarray(dy, dtype=np.float)
        _validate_offset('x', dx)
        _validate_offset('y', dy)
        healpix_index, dx, dy = np.broadcast_arrays(healpix_index, dx, dy)
        dx = dx.ravel()
        dy = dy.ravel()

    shape = healpix_index.shape
    healpix_index = healpix_index.ravel()
    nside = int(nside)

    _validate_healpix_index('healpix_index', healpix_index, nside)
    _validate_nside(nside)
    order = _validate_order(order)

    if dx is None:
        lon, lat = core_cython.healpix_to_lonlat(healpix_index, nside, order)
    else:
        lon, lat = core_cython.healpix_with_offset_to_lonlat(healpix_index, dx, dy, nside, order)

    lon = Longitude(lon, unit=u.rad, copy=False)
    lat = Latitude(lat, unit=u.rad, copy=False)

    return _restore_shape(lon, lat, shape=shape)
Esempio n. 18
0
    def prepare_plot(self,
                     cats=None,
                     mnts=None,
                     imgs=None,
                     nmls=None,
                     selected=None,
                     model=None):
        stars = list()
        for i, ct in enumerate(cats):
            if not i in selected:
                #self.lg.debug('star: {} dropped'.format(i))
                continue

            mt = mnts[i]  # readability
            mts = mt.represent_as(SphericalRepresentation)
            # ToDo may not the end of the story
            cts = ct.represent_as(SphericalRepresentation)
            df_lon = Longitude(cts.lon.radian - mts.lon.radian,
                               u.radian,
                               wrap_angle=Angle(np.pi, u.radian))
            df_lat = Latitude(cts.lat.radian - mts.lat.radian, u.radian)
            #print(df_lat,df_lon)
            #if df_lat.radian < 0./60./180.*np.pi:
            #  pass
            #elif df_lat.radian > 20./60./180.*np.pi:
            #  pass
            #else:
            #  continue
            #  residuum: difference st.cats(fit corrected) - st.star
            #
            res_lon = Longitude(float(
                model.d_lon(cts.lon.radian, cts.lat.radian,
                            cts.lon.radian - mts.lon.radian)),
                                u.radian,
                                wrap_angle=Angle(np.pi, u.radian))

            res_lat = Latitude(
                float(
                    model.d_lat(cts.lon.radian, cts.lat.radian,
                                cts.lat.radian - mts.lat.radian)), u.radian)

            try:
                image_fn = imgs[i]
            except:
                image_fn = 'no image file'
            try:
                nml_id = nmls[i]
            except:
                nml_id = 'no nml_id'
            st = Point(
                cat_lon=cts.lon,
                cat_lat=cts.lat,
                mnt_lon=mts.lon,
                mnt_lat=mts.lat,
                df_lat=df_lat,
                df_lon=df_lon,
                res_lat=res_lat,
                res_lon=res_lon,
                image_fn=image_fn,
                nml_id=nml_id,
            )
            stars.append(st)

        return stars
Esempio n. 19
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")
            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'] == 2:
                wcsin = wcs.WCS(header, naxis=[wcs.WCSSUB_CELESTIAL])
                xy = objects[:,
                             catParNames.index("x"):catParNames.index("x") +
                             2].astype(float)
                objects = np.concatenate((objects, wcsin.wcs_pix2world(xy, 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"])
            else:
                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
                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"])
        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 - 2] if header['naxis'] == 2 else objects[src][n_par - 3]
            lat = objects[src][
                n_par - 1] if header['naxis'] == 2 else 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 with the following error:")
        err.warning("  {0:}".format(sys.exc_info()))

    return (objects, catParNames, catParFormt, catParUnits)
Esempio n. 20
0
# Choose random points on the surface of a sphere
# https://mathworld.wolfram.com/SpherePointPicking.html
rand1, rand2 = np.random.uniform(0,1,n), np.random.uniform(0,1,n)
lons = np.array([(2*np.pi*u * (180/np.pi))-180 for u in rand1])
lats = np.array([(np.arccos(2*v-1)*(180/np.pi)) - 90 for v in rand2])

crd = np.array([*zip(lats,lons)])

lats = crd[:,0]
lons = crd[:,1]

lons = lons * u.Unit('deg')
lats = lats * u.Unit('deg')

lons = Longitude(lons)
lats = Latitude(lats)

locs = EarthLocation.from_geodetic(lon=lons, lat=lats)

pos = np.array([locs.get_gcrs(i).cartesian.xyz.value for i in ts])
print(pos.shape)

names = [str(i).zfill(3) for i in range(len(crd))]
bodies = [Body(names[i], pos[:,:,i], times) for i in range(len(locs))]
colors = ['blue']*len(locs)
sizes = [1]*len(locs)

anim = play(bodies, names, colors, sizes, legend=False, path=False)
plt.show()
Esempio n. 21
0
def test_heliographic_latitude(generic_map):
    assert u.allclose(generic_map.heliographic_latitude,
                      Latitude(sun.B0(generic_map.date)))
Esempio n. 22
0
def test_representations_api():
    from astropy.coordinates.representation import SphericalRepresentation, \
        UnitSphericalRepresentation, PhysicsSphericalRepresentation, \
        CartesianRepresentation
    from astropy.coordinates import Angle, Longitude, Latitude, Distance

    # <-----------------Classes for representation of coordinate data-------------->
    # These classes inherit from a common base class and internally contain Quantity
    # objects, which are arrays (although they may act as scalars, like numpy's
    # length-0  "arrays")

    # They can be initialized with a variety of ways that make intuitive sense.
    # Distance is optional.
    UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg)
    UnitSphericalRepresentation(lon=8 * u.hourangle, lat=5 * u.deg)
    SphericalRepresentation(lon=8 * u.hourangle,
                            lat=5 * u.deg,
                            distance=10 * u.kpc)

    # In the initial implementation, the lat/lon/distance arguments to the
    # initializer must be in order. A *possible* future change will be to allow
    # smarter guessing of the order.  E.g. `Latitude` and `Longitude` objects can be
    # given in any order.
    UnitSphericalRepresentation(Longitude(8, u.hour), Latitude(5, u.deg))
    SphericalRepresentation(Longitude(8, u.hour), Latitude(5, u.deg),
                            Distance(10, u.kpc))

    # Arrays of any of the inputs are fine
    UnitSphericalRepresentation(lon=[8, 9] * u.hourangle, lat=[5, 6] * u.deg)

    # Default is to copy arrays, but optionally, it can be a reference
    UnitSphericalRepresentation(lon=[8, 9] * u.hourangle,
                                lat=[5, 6] * u.deg,
                                copy=False)

    # strings are parsed by `Latitude` and `Longitude` constructors, so no need to
    # implement parsing in the Representation classes
    UnitSphericalRepresentation(lon=Angle('2h6m3.3s'), lat=Angle('0.1rad'))

    # Or, you can give `Quantity`s with keywords, and they will be internally
    # converted to Angle/Distance
    c1 = SphericalRepresentation(lon=8 * u.hourangle,
                                 lat=5 * u.deg,
                                 distance=10 * u.kpc)

    # Can also give another representation object with the `reprobj` keyword.
    c2 = SphericalRepresentation.from_representation(c1)

    #  distance, lat, and lon typically will just match in shape
    SphericalRepresentation(lon=[8, 9] * u.hourangle,
                            lat=[5, 6] * u.deg,
                            distance=[10, 11] * u.kpc)
    # if the inputs are not the same, if possible they will be broadcast following
    # numpy's standard broadcasting rules.
    c2 = SphericalRepresentation(lon=[8, 9] * u.hourangle,
                                 lat=[5, 6] * u.deg,
                                 distance=10 * u.kpc)
    assert len(c2.distance) == 2
    # when they can't be broadcast, it is a ValueError (same as Numpy)
    with raises(ValueError):
        c2 = UnitSphericalRepresentation(lon=[8, 9, 10] * u.hourangle,
                                         lat=[5, 6] * u.deg)

    # It's also possible to pass in scalar quantity lists with mixed units. These
    # are converted to array quantities following the same rule as `Quantity`: all
    # elements are converted to match the first element's units.
    c2 = UnitSphericalRepresentation(
        lon=Angle([8 * u.hourangle, 135 * u.deg]),
        lat=Angle([5 * u.deg, (6 * np.pi / 180) * u.rad]))
    assert c2.lat.unit == u.deg and c2.lon.unit == u.hourangle
    npt.assert_almost_equal(c2.lon[1].value, 9)

    # The Quantity initializer itself can also be used to force the unit even if the
    # first element doesn't have the right unit
    lon = u.Quantity([120 * u.deg, 135 * u.deg], u.hourangle)
    lat = u.Quantity([(5 * np.pi / 180) * u.rad, 0.4 * u.hourangle], u.deg)
    c2 = UnitSphericalRepresentation(lon, lat)

    # regardless of how input, the `lat` and `lon` come out as angle/distance
    assert isinstance(c1.lat, Angle)
    assert isinstance(c1.lat, Latitude)  # `Latitude` is an `Angle` subclass
    assert isinstance(c1.distance, Distance)

    # but they are read-only, as representations are immutable once created
    with raises(AttributeError):
        c1.lat = Latitude(5, u.deg)
    # Note that it is still possible to modify the array in-place, but this is not
    # sanctioned by the API, as this would prevent things like caching.
    c2.lat[:] = [0] * u.deg  # possible, but NOT SUPPORTED

    # To address the fact that there are various other conventions for how spherical
    # coordinates are defined, other conventions can be included as new classes.
    # Later there may be other conventions that we implement - for now just the
    # physics convention, as it is one of the most common cases.
    c3 = PhysicsSphericalRepresentation(phi=120 * u.deg,
                                        theta=85 * u.deg,
                                        r=3 * u.kpc)

    # first dimension must be length-3 if a lone `Quantity` is passed in.
    c1 = CartesianRepresentation(np.random.randn(3, 100) * u.kpc)
    assert c1.xyz.shape[0] == 3
    assert c1.xyz.unit == u.kpc
    assert c1.x.shape[0] == 100
    assert c1.y.shape[0] == 100
    assert c1.z.shape[0] == 100
    # can also give each as separate keywords
    CartesianRepresentation(x=np.random.randn(100) * u.kpc,
                            y=np.random.randn(100) * u.kpc,
                            z=np.random.randn(100) * u.kpc)
    # if the units don't match but are all distances, they will automatically be
    # converted to match `x`
    xarr, yarr, zarr = np.random.randn(3, 100)
    c1 = CartesianRepresentation(x=xarr * u.kpc,
                                 y=yarr * u.kpc,
                                 z=zarr * u.kpc)
    c2 = CartesianRepresentation(x=xarr * u.kpc, y=yarr * u.kpc, z=zarr * u.pc)
    assert c1.xyz.unit == c2.xyz.unit == u.kpc
    assert_allclose((c1.z / 1000) - c2.z, 0 * u.kpc, atol=1e-10 * u.kpc)

    # representations convert into other representations via  `represent_as`
    srep = SphericalRepresentation(lon=90 * u.deg,
                                   lat=0 * u.deg,
                                   distance=1 * u.pc)
    crep = srep.represent_as(CartesianRepresentation)
    assert_allclose(crep.x, 0 * u.pc, atol=1e-10 * u.pc)
    assert_allclose(crep.y, 1 * u.pc, atol=1e-10 * u.pc)
    assert_allclose(crep.z, 0 * u.pc, atol=1e-10 * u.pc)
Esempio n. 23
0
def true_declination(t='now'):
    result = np.cos(true_longitude(t))
    result = result * u.deg
    return Latitude(result)
Esempio n. 24
0
 def __init__(self, lon_0, lat_0):
     self.parameters = Parameters(
         [Parameter("lon_0", Longitude(lon_0)), Parameter("lat_0", Latitude(lat_0))]
     )
Esempio n. 25
0
scc = sc.copy()
scc.representation_type = 'cartesian'
tm = Time([2450814.5, 2450815.5], format='jd', scale='tai', location=el)

# NOTE: in the test below the name of the column "x" for the Quantity is
# important since it tests the fix for #10215 (namespace clash, where "x"
# clashes with "el2.x").
mixin_cols = {
    'tm': tm,
    'dt': TimeDelta([1, 2] * u.day),
    'sc': sc,
    'scc': scc,
    'scd': SkyCoord([1, 2], [3, 4], [5, 6], unit='deg,deg,m', frame='fk4',
                    obstime=['J1990.5', 'J1991.5']),
    'x': [1, 2] * u.m,
    'lat': Latitude([1, 2] * u.deg),
    'lon': Longitude([1, 2] * u.deg, wrap_angle=180. * u.deg),
    'ang': Angle([1, 2] * u.deg),
    'el2': el2,
    'sr': sr,
    'cr': cr,
    'sd': sd,
    'srd': srd,
}

time_attrs = ['value', 'shape', 'format', 'scale', 'location']
compare_attrs = {
    'c1': ['data'],
    'c2': ['data'],
    'tm': time_attrs,
    'dt': ['shape', 'value', 'format', 'scale'],
Esempio n. 26
0
  def sofa(self,tf=None,sky=None,simbad=False):
    tc=phpa=rh=0.
    if sky is not None:
      tc=sky.temperature
      phpa=sky.pressure
      rh=sky.humidity
      
    wl=0.55
    utc1=c_double()
    utc2=c_double()
    dtt=tf.obstime.datetime.timetuple()
    if sf.iauDtf2d (b'UTC',
                    dtt.tm_year,
                    dtt.tm_mon,
                    dtt.tm_mday,
                    dtt.tm_hour,
                    dtt.tm_min,
                    dtt.tm_sec,
                    byref(utc1),
                    byref(utc2)):
      self.lg.error('sofa: iauDtf2d failed')
      return None,None,None

    tai1=c_double()
    tai2=c_double()
    if sf.iauUtctai(utc1,utc2,byref(tai1), byref(tai2)):
      self.lg.error('sofa: iauUtctai failed')
      return None,None,None
    
    tt1=c_double()
    tt2=c_double()
    if sf.iauTaitt(tai1,tai2,byref(tt1), byref(tt2)):
      self.lg.error('sofa: iauTaitt failed')
      return None,None,None
    
    #/* EOPs:  polar motion in radians, UT1-UTC in seconds. */
    #xp = 50.995e-3 * DAS2R
    #yp = 376.723e-3 * DAS2R
    #dut1 = 155.0675e-3
    iers_b = iers.IERS_B.open()
    ###dt=dateutil.parser.parse('2013-04-04T23:15:43.55Z')
    dtt=Time(tf.obstime.datetime)
    xp=yp=xp_u=yp_u=0.
    try:
      dut1_u=dtt.delta_ut1_utc = iers_b.ut1_utc(dtt)
      (xp_u,yp_u)=iers_b.pm_xy(dtt)
      dut1=dut1_u.value
      xp=xp_u.value*DAS2R
      yp=yp_u.value*DAS2R
    except iers.IERSRangeError as e:
      self.lg.error('sofa: IERSRangeError setting dut1,xp,yp to zero')
      dut1=0.
      
    #/* Corrections to IAU 2000A CIP (radians). */
    #dx = 0.269e-3 * DAS2R
    #dy = -0.274e-3 * DAS2R
    dx=dy=0.              
    rc=tf.ra.radian
    dc=tf.dec.radian
    pr=pd=px=rv=0.
    # identify star on SIMBAD
    if simbad:
      rslt_tbl = self.smbd.query_region(tf,radius='0d1m0s')
      #print(rslt_tbl.info)
      #MAIN_ID          RA           DEC      RA_PREC DEC_PREC    PMRA     PMDEC   PMRA_PREC PMDEC_PREC RV_VALUE PM_QUAL
      #             "h:m:s"       "d:m:s"                      mas / yr  mas / yr                       km / s
      #------------ ------------- ------------- ------- -------- --------- --------- --------- ---------- -------- -------
      #CPD-80  1068 23 21 32.1685 -79 31 09.138  8        8     3.900    -2.400         2       2        0.341       B                 
      #print(rslt_tbl['MAIN_ID','RA','DEC','RA_PREC','DEC_PREC','PMRA','PMDEC','PMRA_PREC','PMDEC_PREC','RV_VALUE','PM_QUAL'])
      #
      if len(rslt_tbl['RA'])>1:
        rslt_tbl.sort('FLUX_V')
        self.lg.warn('transform_to_altaz: found mor than one entry in SIMBAD table, using brightest main_id:{}'.format(rslt_tbl['MAIN_ID'][0]))
        
        
      print(rslt_tbl)
      (h,m,s)=str(rslt_tbl['RA'][0]).split()      
      rc=Longitude('{0} {1} {2} hours'.format(h,m,s)).radian
      #
      (d,m,s)=str(rslt_tbl['DEC'][0]).split()
      dc=Latitude('{0} {1} {2} degrees'.format(d,m,s)).radian
      #/* Proper motion: RA/Dec derivatives, epoch J2000.0. */
      #/* pr = atan2 ( -354.45e-3 * DAS2R, cos(dc) ); */
      #/* pd = 595.35e-3 * DAS2R; */
      # 
      pmra=float(rslt_tbl['PMRA'][0])
      pmrd=float(rslt_tbl['PMDEC'][0])
      pr=np.arctan2(pmra*DAS2R,np.cos(dc))
      pd=pmrd * DAS2R
      #/* Parallax (arcsec) and recession speed (km/s). */
      #/* px = 164.99e-3; */
      #/* rv = 0.0; */
      # it is a masked table
      px = float(rslt_tbl['PLX_VALUE'][0])
      if np.isnan(px):
        px=0.
      if np.isnan(rv):
        rv = float(rslt_tbl['RV_VALUE'][0])
      
    #/* ICRS to observed. */
    aob=c_double()
    zob=c_double()
    hob=c_double()
    dob=c_double()
    rob=c_double()
    eo= c_double()
    phi=c_double(self.phi.radian)
    elong=c_double(self.elong.radian)
    hm=c_double(self.hm)

    if sf.iauAtco13(rc,dc,pr,pd,px,rv,utc1,utc2,dut1,
                    elong,phi,hm,xp,yp,phpa,tc,rh,wl,
                    byref(aob),
                    byref(zob),
                    byref(hob),
                    byref(dob),
                    byref(rob),
                    byref(eo)):
      self.lg.error('sofa: iauAtco13 failed')
      return None,None,None
    
    aa=SkyCoord(az=aob.value,alt=(np.pi/2.-zob.value),unit=(u.radian,u.radian),frame='altaz',location=self.obs_astropy,obstime=dtt,obswl=wl*u.micron, pressure=phpa*u.hPa,temperature=tc*u.deg_C,relative_humidity=rh)
    # observed RA,Dec rob,dob
    # observed HA,Dec hob,dec
    hd=SkyCoord(ra=hob.value,dec=dob,unit=(u.radian,u.radian),frame='gcrs',location=self.obs_astropy,obstime=dtt,obswl=wl*u.micron, pressure=phpa*u.hPa,temperature=tc*u.deg_C,relative_humidity=rh)
    rd=SkyCoord(ra=rob.value,dec=dob,unit=(u.radian,u.radian),frame='gcrs',location=self.obs_astropy,obstime=dtt,obswl=wl*u.micron, pressure=phpa*u.hPa,temperature=tc*u.deg_C,relative_humidity=rh)
    
    if abs(eo.value)> 1.: 
      self.lg.error('sofa: eo=ERA-GST: {}'.format(eo.value))
      
    return aa,hd,rd
Esempio n. 27
0
 def from_tree(cls, node, ctx):
     return Latitude(super().from_tree(node, ctx))
Esempio n. 28
0
def apparent_latitude(t='now'):  # pylint: disable=W0613
    """
    Returns the true latitude. Set to 0 here.

    """
    return Latitude(0.0 * u.deg)
Esempio n. 29
0
 def __init__(self, lon_0, lat_0, sigma):
     self.parameters = Parameters([
         Parameter('lon_0', Longitude(lon_0)),
         Parameter('lat_0', Latitude(lat_0)),
         Parameter('sigma', Angle(sigma))
     ])
Esempio n. 30
0
def doTest():
    print(colored('Testing Coordinates Module', 'magenta'))

    print(colored('Testing Ra', 'magenta'))
    print(colored('Testing Default Constructor', 'cyan'))
    ra = NumCpp.RaDouble()
    print(colored('\tPASS', 'green'))

    print(colored('Testing Degree Constructor', 'cyan'))
    randDegrees = np.random.rand(1).item() * 360
    ra = NumCpp.RaDouble(randDegrees)
    raPy = Longitude(randDegrees, unit=u.deg)
    if (round(ra.degrees(), 9) == round(randDegrees, 9)
            and ra.hours() == raPy.hms.h and ra.minutes() == raPy.hms.m
            and round(ra.seconds(), 9) == round(raPy.hms.s, 9)
            and round(ra.radians(), 9) == round(np.deg2rad(randDegrees), 9)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing hms Constructor', 'cyan'))
    hours = np.random.randint(0, 24, [
        1,
    ], dtype=np.uint8).item()
    minutes = np.random.randint(0, 60, [
        1,
    ], dtype=np.uint8).item()
    seconds = np.random.rand(1).astype(np.float32).item() * 60
    ra = NumCpp.RaDouble(hours, minutes, seconds)
    degreesPy = (hours + minutes / 60 + seconds / 3600) * 15
    if (round(ra.degrees(), 9) == round(degreesPy, 9) and ra.hours() == hours
            and ra.minutes() == minutes
            and round(ra.seconds(), 9) == round(seconds, 9)
            and round(ra.radians(), 9) == round(np.deg2rad(degreesPy), 9)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing astype', 'cyan'))
    raF = ra.asFloat()
    if (round(ra.degrees(), 4) == round(raF.degrees(), 4)
            and ra.hours() == raF.hours() and ra.minutes() == raF.minutes()
            and round(ra.seconds(), 4) == round(raF.seconds(), 4)
            and round(ra.radians(), 4) == round(raF.radians(), 4)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing equality operator', 'cyan'))
    ra2 = NumCpp.RaDouble(ra)
    if ra == ra2:
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing not equality operator', 'cyan'))
    randDegrees = np.random.rand(1).item() * 360
    ra2 = NumCpp.RaDouble(randDegrees)
    if ra != ra2:
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing print', 'cyan'))
    ra.print()
    print(colored('\tPASS', 'green'))

    print(colored('Testing Dec', 'magenta'))
    print(colored('Testing Default Constructor', 'cyan'))
    dec = NumCpp.DecDouble()
    print(colored('\tPASS', 'green'))

    print(colored('Testing Degree Constructor', 'cyan'))
    randDegrees = np.random.rand(1).item() * 180 - 90
    dec = NumCpp.DecDouble(randDegrees)
    decPy = Latitude(randDegrees, unit=u.deg)
    sign = NumCpp.Sign.NEGATIVE if randDegrees < 0 else NumCpp.Sign.POSITIVE
    if (round(dec.degrees(), 8) == round(randDegrees, 8) and dec.sign() == sign
            and dec.degreesWhole() == abs(decPy.dms.d)
            and dec.minutes() == abs(decPy.dms.m)
            and round(dec.seconds(), 8) == round(abs(decPy.dms.s), 8)
            and round(dec.radians(), 8) == round(np.deg2rad(randDegrees), 8)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing dms Constructor', 'cyan'))
    sign = NumCpp.Sign.POSITIVE if np.random.randint(
        -1, 1) == 0 else NumCpp.Sign.NEGATIVE
    degrees = np.random.randint(0, 91, [
        1,
    ], dtype=np.uint8).item()
    minutes = np.random.randint(0, 60, [
        1,
    ], dtype=np.uint8).item()
    seconds = np.random.rand(1).astype(np.float32).item() * 60
    dec = NumCpp.DecDouble(sign, degrees, minutes, seconds)
    degreesPy = degrees + minutes / 60 + seconds / 3600
    if sign == NumCpp.Sign.NEGATIVE:
        degreesPy *= -1
    if (dec.sign() == sign and round(dec.degrees(), 9) == round(degreesPy, 9)
            and dec.degreesWhole() == degrees and dec.minutes() == minutes
            and round(dec.seconds(), 9) == round(seconds, 9)
            and round(dec.radians(), 8) == round(np.deg2rad(degreesPy), 8)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing astype', 'cyan'))
    decF = dec.asFloat()
    if (round(dec.degrees(), 4) == round(decF.degrees(), 4)
            and dec.sign() == decF.sign()
            and dec.degreesWhole() == decF.degreesWhole()
            and dec.minutes() == decF.minutes()
            and round(dec.seconds(), 4) == round(decF.seconds(), 4)
            and round(dec.radians(), 4) == round(decF.radians(), 4)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing equality operator', 'cyan'))
    dec2 = NumCpp.DecDouble(dec)
    if dec == dec2:
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing not equality operator', 'cyan'))
    randDegrees = np.random.rand(1).item() * 180 - 90
    dec2 = NumCpp.DecDouble(randDegrees)
    if dec != dec2:
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing print', 'cyan'))
    dec.print()
    print(colored('\tPASS', 'green'))

    print(colored('Testing Coordinate', 'magenta'))
    print(colored('Testing Default Constructor', 'cyan'))
    coord = NumCpp.CoordinateDouble()
    print(colored('\tPASS', 'green'))

    print(colored('Testing Degree Constructor', 'cyan'))
    raDegrees = np.random.rand(1).item() * 360
    ra = NumCpp.RaDouble(raDegrees)
    decDegrees = np.random.rand(1).item() * 180 - 90
    dec = NumCpp.DecDouble(decDegrees)

    pyCoord = SkyCoord(raDegrees, decDegrees, unit=u.deg)
    cCoord = NumCpp.CoordinateDouble(raDegrees, decDegrees)
    if (cCoord.ra() == ra and cCoord.dec() == dec
            and round(cCoord.x(), 10) == round(pyCoord.cartesian.x.value, 10)
            and round(cCoord.y(), 10) == round(pyCoord.cartesian.y.value, 10)
            and round(cCoord.z(), 10) == round(pyCoord.cartesian.z.value, 10)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing Ra/Dec Constructor', 'cyan'))
    raDegrees = np.random.rand(1).item() * 360
    ra = NumCpp.RaDouble(raDegrees)
    decDegrees = np.random.rand(1).item() * 180 - 90
    dec = NumCpp.DecDouble(decDegrees)

    pyCoord = SkyCoord(raDegrees, decDegrees, unit=u.deg)
    cCoord = NumCpp.CoordinateDouble(ra, dec)
    if (cCoord.ra() == ra and cCoord.dec() == dec
            and round(cCoord.x(), 10) == round(pyCoord.cartesian.x.value, 10)
            and round(cCoord.y(), 10) == round(pyCoord.cartesian.y.value, 10)
            and round(cCoord.z(), 10) == round(pyCoord.cartesian.z.value, 10)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing x/y/z Constructor', 'cyan'))
    raDegrees = np.random.rand(1).item() * 360
    ra = NumCpp.RaDouble(raDegrees)
    decDegrees = np.random.rand(1).item() * 180 - 90
    dec = NumCpp.DecDouble(decDegrees)
    pyCoord = SkyCoord(raDegrees, decDegrees, unit=u.deg)
    cCoord = NumCpp.CoordinateDouble(pyCoord.cartesian.x.value,
                                     pyCoord.cartesian.y.value,
                                     pyCoord.cartesian.z.value)
    if (round(cCoord.ra().degrees(), 9) == round(ra.degrees(), 9)
            and round(cCoord.dec().degrees(), 9) == round(dec.degrees(), 9)
            and round(cCoord.x(), 9) == round(pyCoord.cartesian.x.value, 9)
            and round(cCoord.y(), 9) == round(pyCoord.cartesian.y.value, 9)
            and round(cCoord.z(), 9) == round(pyCoord.cartesian.z.value, 9)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing NdArray Constructor', 'cyan'))
    raDegrees = np.random.rand(1).item() * 360
    ra = NumCpp.RaDouble(raDegrees)
    decDegrees = np.random.rand(1).item() * 180 - 90
    dec = NumCpp.DecDouble(decDegrees)
    pyCoord = SkyCoord(raDegrees, decDegrees, unit=u.deg)
    vec = np.asarray([
        pyCoord.cartesian.x.value, pyCoord.cartesian.y.value,
        pyCoord.cartesian.z.value
    ])
    cVec = NumCpp.NdArray(1, 3)
    cVec.setArray(vec)
    cCoord = NumCpp.CoordinateDouble(cVec)
    if (round(cCoord.ra().degrees(), 9) == round(ra.degrees(), 9)
            and round(cCoord.dec().degrees(), 9) == round(dec.degrees(), 9)
            and round(cCoord.x(), 9) == round(pyCoord.cartesian.x.value, 9)
            and round(cCoord.y(), 9) == round(pyCoord.cartesian.y.value, 9)
            and round(cCoord.z(), 9) == round(pyCoord.cartesian.z.value, 9)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing hms/dms Constructor', 'cyan'))
    raHours = np.random.randint(0, 24, [
        1,
    ], dtype=np.uint8).item()
    raMinutes = np.random.randint(0, 60, [
        1,
    ], dtype=np.uint8).item()
    raSeconds = np.random.rand(1).astype(np.float32).item() * 60
    raDegreesPy = (raHours + raMinutes / 60 + raSeconds / 3600) * 15

    decSign = NumCpp.Sign.POSITIVE if np.random.randint(
        -1, 1) == 0 else NumCpp.Sign.NEGATIVE
    decDegrees = np.random.randint(0, 91, [
        1,
    ], dtype=np.uint8).item()
    decMinutes = np.random.randint(0, 60, [
        1,
    ], dtype=np.uint8).item()
    decSeconds = np.random.rand(1).astype(np.float32).item() * 60
    decDegreesPy = decDegrees + decMinutes / 60 + decSeconds / 3600
    if decSign == NumCpp.Sign.NEGATIVE:
        decDegreesPy *= -1

    cCoord = NumCpp.CoordinateDouble(raHours, raMinutes, raSeconds, decSign,
                                     decDegrees, decMinutes, decSeconds)
    cRa = cCoord.ra()
    cDec = cCoord.dec()
    pyCoord = SkyCoord(raDegreesPy, decDegreesPy, unit=u.deg)
    if (round(cRa.degrees(), 9) == round(raDegreesPy, 9)
            and cRa.hours() == raHours and cRa.minutes() == raMinutes
            and round(cRa.seconds(), 9) == round(raSeconds, 9)
            and cDec.sign() == decSign
            and round(cDec.degrees(), 9) == round(decDegreesPy, 9)
            and cDec.degreesWhole() == decDegrees
            and cDec.minutes() == decMinutes
            and round(cDec.seconds(), 9) == round(decSeconds, 9)
            and round(cCoord.x(), 9) == round(pyCoord.cartesian.x.value, 9)
            and round(cCoord.y(), 9) == round(pyCoord.cartesian.y.value, 9)
            and round(cCoord.z(), 9) == round(pyCoord.cartesian.z.value, 9)):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing equality operator', 'cyan'))
    cCoord2 = NumCpp.CoordinateDouble(cCoord)
    if cCoord2 == cCoord:
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing not equality operator', 'cyan'))
    raDegrees = np.random.rand(1).item() * 360
    decDegrees = np.random.rand(1).item() * 180 - 90
    cCoord2 = NumCpp.CoordinateDouble(raDegrees, decDegrees)
    if cCoord2 != cCoord:
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing xyz', 'cyan'))
    xyz = [cCoord.x(), cCoord.y(), cCoord.z()]
    if np.array_equal(cCoord.xyz().getNumpyArray().flatten(), xyz):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing degreeSeperation Coordinate', 'cyan'))
    pyCoord2 = SkyCoord(cCoord2.ra().degrees(),
                        cCoord2.dec().degrees(),
                        unit=u.deg)
    cDegSep = cCoord.degreeSeperation(cCoord2)
    pyDegSep = pyCoord.separation(pyCoord2).value
    if round(cDegSep, 9) == round(pyDegSep, 9):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing radianSeperation Coordinate', 'cyan'))
    cRadSep = cCoord.radianSeperation(cCoord2)
    pyRadSep = np.deg2rad(pyDegSep)
    if round(cRadSep, 9) == round(pyRadSep, 9):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing degreeSeperation Vector', 'cyan'))
    vec2 = np.asarray(
        [pyCoord2.cartesian.x, pyCoord2.cartesian.y, pyCoord2.cartesian.z])
    cArray = NumCpp.NdArray(1, 3)
    cArray.setArray(vec2)
    cDegSep = cCoord.degreeSeperation(cArray)
    if round(cDegSep, 9) == round(pyDegSep, 9):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing radianSeperation Vector', 'cyan'))
    cArray = NumCpp.NdArray(1, 3)
    cArray.setArray(vec2)
    cDegSep = cCoord.radianSeperation(cArray)
    if round(cDegSep, 9) == round(pyRadSep, 9):
        print(colored('\tPASS', 'green'))
    else:
        print(colored('\tFAIL', 'red'))

    print(colored('Testing print', 'cyan'))
    cCoord.print()
    print(colored('\tPASS', 'green'))
Esempio n. 31
0
class SkyCatalog:
	def __init__(self, sun_only = False, moon_only = False):
		if sun_only:
			self.ephemerides = [ephem.Sun()]
			self.data = None
		elif moon_only:
			self.ephemerides = [ephem.Moon()]
			self.data = None
		else:
			self.ephemerides = [ephem.Venus(), ephem.Mars(), ephem.Jupiter(), ephem.Saturn(), ephem.Moon(), ephem.Sun()]
			
			self.data = ascii.read(Configuration.star_catalog_file, guess=False, format='fixed_width_no_header', names=('HR', 'Name', 'DM', 'HD', 'SAO', 'FK5', 'IRflag', 'r_IRflag', 'Multiple', 'ADS', 'ADScomp', 'VarID', 'RAh1900', 'RAm1900', 'RAs1900', 'DE-1900', 'DEd1900', 'DEm1900', 'DEs1900', 'RAh', 'RAm', 'RAs', 'DE-', 'DEd', 'DEm', 'DEs', 'GLON', 'GLAT', 'Vmag', 'n_Vmag', 'u_Vmag', 'B-V', 'u_B-V', 'U-B', 'u_U-B', 'R-I', 'n_R-I', 'SpType', 'n_SpType', 'pmRA', 'pmDE', 'n_Parallax', 'Parallax', 'RadVel', 'n_RadVel', 'l_RotVel', 'RotVel', 'u_RotVel', 'Dmag', 'Sep', 'MultID', 'MultCnt', 'NoteFlag'), col_starts=(0, 4, 14, 25, 31, 37, 41, 42, 43, 44, 49, 51, 60, 62, 64, 68, 69, 71, 73, 75, 77, 79, 83, 84, 86, 88, 90, 96, 102, 107, 108, 109, 114, 115, 120, 121, 126, 127, 147, 148, 154, 160, 161, 166, 170, 174, 176, 179, 180, 184, 190, 194, 196), col_ends=(3, 13, 24, 30, 36, 40, 41, 42, 43, 48, 50, 59, 61, 63, 67, 68, 70, 72, 74, 76, 78, 82, 83, 85, 87, 89, 95, 101, 106, 107, 108, 113, 114, 119, 120, 125, 126, 146, 147, 153, 159, 160, 165, 169, 173, 175, 178, 179, 183, 189, 193, 195, 196))
			
			# removed masked rows
			
			self.data = self.data[:][~np.ma.getmaskarray(self.data['DE-'])]
		
	def setLocation(self, location):
		self.location = location
		
	def setTime(self, time):
		self.time = time
		
	def calculate(self):
		ephem_location = ephem.Observer()
		ephem_location.lat = self.location.latitude.to(u.rad) / u.rad
		ephem_location.lon = self.location.longitude.to(u.rad) / u.rad
		ephem_location.elevation = self.location.height / u.meter
		ephem_location.date = ephem.Date(self.time.datetime)

		if self.data is None:
			self.alt = Latitude([], unit=u.deg)
			self.az = Longitude([], unit=u.deg)
			self.names = Column([], dtype=np.str)
			self.vmag = Column([])
		else:
			ra = Longitude((self.data['RAh'], self.data['RAm'], self.data['RAs']), u.h)
			dec = Latitude((np.core.defchararray.add(self.data['DE-'], self.data['DEd'].astype(str)).astype(int), self.data['DEm'], self.data['DEs']), u.deg)
			c = SkyCoord(ra, dec, frame='icrs')
			altaz = c.transform_to(AltAz(obstime=self.time, location=self.location))
			self.alt = altaz.alt
			self.az = altaz.az

			self.names = self.data['Name']
			self.vmag = self.data['Vmag']

		for ephemeris in self.ephemerides:
			ephemeris.compute(ephem_location)
			self.vmag = self.vmag.insert(0, ephemeris.mag)
			self.alt = self.alt.insert(0, (ephemeris.alt.znorm * u.rad).to(u.deg))
			self.az = self.az.insert(0, (ephemeris.az * u.rad).to(u.deg))
			self.names = self.names.insert(0, ephemeris.name)
		
		return self.names, self.vmag, self.alt, self.az

	def filter(self, min_alt, max_mag):
		show = self.alt >= min_alt

		names = self.names[show]
		vmag = self.vmag[show]
		alt = self.alt[show]
		az = self.az[show]

		show_mags = vmag < max_mag

		names = names[show_mags]
		vmag = vmag[show_mags]
		alt = alt[show_mags]
		az = az[show_mags]
		
		return names, vmag, alt, az
Esempio n. 32
0
 def __init__(self, lon_0, lat_0):
     self.parameters = ParameterList([
         Parameter('lon_0', Longitude(lon_0)),
         Parameter('lat_0', Latitude(lat_0))
     ])
Esempio n. 33
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)
    'tm':
    tm,
    'dt':
    TimeDelta([1, 2] * u.day),
    'sc':
    sc,
    'scc':
    scc,
    'scd':
    SkyCoord([1, 2], [3, 4], [5, 6],
             unit='deg,deg,m',
             frame='fk4',
             obstime=['J1990.5', 'J1991.5']),
    'q': [1, 2] * u.m,
    'lat':
    Latitude([1, 2] * u.deg),
    'lon':
    Longitude([1, 2] * u.deg, wrap_angle=180. * u.deg),
    'ang':
    Angle([1, 2] * u.deg),
    'el2':
    el2,
}

time_attrs = ['value', 'shape', 'format', 'scale', 'location']
compare_attrs = {
    'c1': ['data'],
    'c2': ['data'],
    'tm': time_attrs,
    'dt': ['shape', 'value', 'format', 'scale'],
    'sc': ['ra', 'dec', 'representation_type', 'frame.name'],