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 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)
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)) ])
def __init__(self, l, b, name=None): self['l'] = Longitude(l, wrap_angle=180. * u.degree) self['b'] = Latitude(b) self['name'] = name
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
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)
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) }
def time_latitude(): Latitude(3.2, u.degree)
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]
def lat(self): if self.lat_str[-1]=='s': m=-1. else: m=1. return m*Latitude(Angle(self.lat_str[:-1]))
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)
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
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
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),
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
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
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)
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
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)
# 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()
def test_heliographic_latitude(generic_map): assert u.allclose(generic_map.heliographic_latitude, Latitude(sun.B0(generic_map.date)))
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)
def true_declination(t='now'): result = np.cos(true_longitude(t)) result = result * u.deg return Latitude(result)
def __init__(self, lon_0, lat_0): self.parameters = Parameters( [Parameter("lon_0", Longitude(lon_0)), Parameter("lat_0", Latitude(lat_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'],
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
def from_tree(cls, node, ctx): return Latitude(super().from_tree(node, ctx))
def apparent_latitude(t='now'): # pylint: disable=W0613 """ Returns the true latitude. Set to 0 here. """ return Latitude(0.0 * u.deg)
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)) ])
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'))
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
def __init__(self, lon_0, lat_0): self.parameters = ParameterList([ Parameter('lon_0', Longitude(lon_0)), Parameter('lat_0', Latitude(lat_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'],