def jd2lst(jd, longitude=0.0): jd0 = int(jd) + 0.5 dd0 = jd0 - 2451545. dd = jd - 2451545. tt = dd / 36525 hh = (jd - jd0) * 24. gmst = 6.697374558 + 0.06570982441908 * dd0 + 1.00273790935 * hh + \ 0.000026 * tt**2 gmstL = coo.Longitude(gmst * uu.hour) lon = coo.Longitude(longitude * uu.degree) return coo.Longitude(gmstL + lon)
def test_cartesian_model( test_data, lon, lat, rotation, deg: bool, expected_data, ): """Test `~trackstream.preprocess.rotated_frame.cartesian_model`.""" # -------------- # setup angle_unit = u.deg if deg else u.rad # get unit # reverse map: value, key map in expected_data rev_names = { v: k for k, v in expected_data.representation_component_names.items() } # -------------- # apply model r, lon, lat = rotated_frame.cartesian_model( test_data.cartesian, lon=lon, lat=lat, rotation=rotation, deg=deg, ) # longitude and latitude lon = np.mod(coord.Longitude(lon, unit=angle_unit), 180 * u.deg) lat = np.mod(coord.Longitude(lat, unit=angle_unit), 180 * u.deg) # -------------- # Testing r, lon, lat expected_r = getattr(expected_data, rev_names["distance"]) expected_lon = getattr(expected_data, rev_names["lon"]) expected_lat = getattr(expected_data, rev_names["lat"]) assert_quantity_allclose(r, expected_r, atol=1e-10 * expected_r.unit) assert_quantity_allclose( lon, np.mod(expected_lon, 180 * u.deg), atol=1e-10 * expected_lon.unit, ) assert_quantity_allclose( lat, np.mod(expected_lat, 180 * u.deg), atol=1e-10 * expected_lat.unit, )
def trace(self, seeds, output): self.validate_seeds(seeds) x, y, z = self.coords_to_xyz(seeds, output) r, lat, phi = astrocoords.cartesian_to_spherical(x, y, z) # Force 360deg wrapping phi = astrocoords.Longitude(phi).to_value(u.rad) s = np.sin(lat).to_value(u.dimensionless_unscaled) rho = np.log(r) seeds = np.atleast_2d(np.stack((phi, s, rho), axis=-1)) # Get a grid vector_grid = self.vector_grid(output) # Do the tracing self.tracer.trace(seeds, vector_grid) xs = self.tracer.xs rots = self.tracer.ROT if np.any(rots == 1): warnings.warn( 'At least one field line ran out of steps during tracing.\n' 'You should probably increase max_steps ' f'(currently set to {self.max_steps}) and try again.') xs = [ np.stack(pfsspy.coords.strum2cart(x[:, 2], x[:, 1], x[:, 0]), axis=-1) for x in xs ] flines = [ fieldline.FieldLine(x[:, 0], x[:, 1], x[:, 2], output) for x in xs ] return fieldline.FieldLines(flines)
def _perform(self): """ Returns an Argument() with the parameters that depends on this operation. """ self.log.info(f"Running {self.__class__.__name__} action") lat=c.Latitude(self.action.args.kd.get('SITELAT'), unit=u.degree) lon=c.Longitude(self.action.args.kd.get('SITELONG'), unit=u.degree) height=float(self.action.args.kd.get('ALT-OBS')) * u.meter loc = c.EarthLocation(lon, lat, height) temperature=float(self.action.args.kd.get('AMBTEMP'))*u.Celsius pressure=self.cfg['Telescope'].getfloat('pressure', 700)*u.mbar altazframe = c.AltAz(location=loc, obstime=self.action.args.kd.obstime(), temperature=temperature, pressure=pressure) moon = c.get_moon(Time(self.action.args.kd.obstime()), location=loc) sun = c.get_sun(Time(self.action.args.kd.obstime())) moon_alt = ((moon.transform_to(altazframe).alt).to(u.degree)).value moon_separation = (moon.separation(self.action.args.header_pointing).to(u.degree)).value\ if self.action.args.header_pointing is not None else None # Moon illumination formula from Meeus, ÒAstronomical # Algorithms". Formulae 46.1 and 46.2 in the 1991 edition, # using the approximation cos(psi) \approx -cos(i). Error # should be no more than 0.0014 (p. 316). moon_illum = 50*(1 - np.sin(sun.dec.radian)*np.sin(moon.dec.radian)\ - np.cos(sun.dec.radian)*np.cos(moon.dec.radian)\ * np.cos(sun.ra.radian-moon.ra.radian)) self.action.args.moon_alt = moon_alt self.action.args.moon_separation = moon_separation self.action.args.moon_illum = moon_illum return self.action.args
def _gal2idx(self, gal): """ Converts from Galactic coordinates to pixel indices. Args: gal (:obj:`astropy.coordinates.SkyCoord`): Galactic coordinates. Must store an array of coordinates (i.e., not be scalar). Returns: ``j, k, mask`` - Pixel indices of the coordinates, as well as a mask of in-bounds coordinates. Outputs have the same shape as the input coordinates. """ # Make sure that l is in domain [-180 deg, 180 deg) l = coordinates.Longitude(gal.l, wrap_angle=180. * units.deg) j = (self._inv_pix_scale * (l.deg - self._l_bounds[0])).astype('i4') k = (self._inv_pix_scale * (gal.b.deg - self._b_bounds[0])).astype('i4') idx = (j < 0) | (j >= self._shape[0]) | (k < 0) | (k >= self._shape[1]) if np.any(idx): j[idx] = -1 k[idx] = -1 return j, k, ~idx
def proc_args(): """ Intelligently read in arguments Check for errors Returns --------- dictionary containing relevant values """ pars = ap.ArgumentParser(description="Locate and process data \ on known pulsars") pars.add_argument("--comp",action="store",choices=["zuul","GB"], required=True,help="select computer system") pars.add_argument("--pos",action="store", help="ra and dec ('hh:mm:ss.ss (-)dd:mm:ss.ss')") pars.add_argument("-p","--period",action="store",default=1.0,type=float, help="period in s") pars.add_argument("-pd","--pdot",action="store",default=0,type=float, help="period derivative in s/s") pars.add_argument("--dm",action="store",default=50,type=float, help="DM in pc/cc") pars.add_argument("-f","--file",action="store", help="file name (assumes file has columns of \ NUMBER, JNAME, RA, DEC, P0, P1, DM)") pars.add_argument("--beam",action="store", help="beam number as integer") pars.add_argument("-n","--nbin",action="store",default=50,type=int, help="number of profile bins") pars.add_argument("--nsub",action="store",default=128,type=int, help="number of channels") pars.add_argument("--npart",action="store",default=40,type=int, help="number of subintegrations") pars.add_argument("--angle",action="store",default=0.5,type=float, help="max offset between beam and pulsar in deg") pars.add_argument("--snr",action="store",default=6,type=float, help="minimum S/N for detection") pars.add_argument("--proc",action="store_true", help="process files") pars.add_argument("--center",action="store_true",dest="find_psr", help="process central (original) beam") pars.add_argument("--pub",action="store_true", help="only process published pulsars") pars.add_argument("--rfi",action="store_true", help="use Scott's options to remove RFI") pars.add_argument("--nonew",action="store_false",dest="pull_new", help="do not copy new fits files into directories") pars.add_argument("-o","--out",action="store",help="output location (default is /users/rspiewak/pulsars/)") args = vars(pars.parse_args()) if args['pos'] != None and len(args["pos"].split()) > 1: ra_astro = coord.Longitude(args["pos"].split()[0],unit="hourangle") dec_astro = coord.Latitude(args["pos"].split()[1],unit="deg") args["ra_psr"] = ra_astro.value args["dec_psr"] = dec_astro.value return args
def helcorr(obs_long, obs_lat, obs_alt, ra2000, dec2000, jd, system="barycentric"): """ calculates heliocentric Julian date, barycentric and heliocentric radial velocity corrections, using astropy functions Parameters --------- obs_long : float Longitude of observatory (degrees, western direction is positive) obs_lat : float Latitude of observatory (degrees) obs_alt : float Altitude of observatory (meters) ra2000 : float Right ascension of object for epoch 2000.0 (hours) dec2000 : float Declination of object for epoch 2000.0 (degrees) jd : float Julian date for the middle of exposure in MJD system : {"barycentric", "heliocentric"}, optional reference system of the result, barycentric: around earth-sun gravity center, heliocentric: around sun, usually barycentric is preferred (default: "barycentric) Returns ------- correction : float radial velocity correction due to barycentre offset hjd : float Heliocentric Julian date for middle of exposure """ # jd = 2400000.5 + jd jd = time.Time(jd, format="mjd") ra = coord.Longitude(ra2000, unit=u.hour) dec = coord.Latitude(dec2000, unit=u.degree) observatory = coord.EarthLocation.from_geodetic(obs_long, obs_lat, height=obs_alt) sky_location = coord.SkyCoord(ra, dec, obstime=jd, location=observatory) times = time.Time(jd, location=observatory) if system == "barycentric": correction = sky_location.radial_velocity_correction().to(u.km / u.s).value ltt = times.light_travel_time(sky_location) elif system == "heliocentric": correction = ( sky_location.radial_velocity_correction("heliocentric").to(u.km / u.s).value ) ltt = times.light_travel_time(sky_location, "heliocentric") else: raise AttributeError( "Could not parse system, values are: ('barycentric', 'heliocentric')" ) times = (times.utc + ltt).value - 2400000 return -correction, times
def decimal_day_to_tuple(day): """ Float day to (h,m,s) tuple @param day : float @return: tuple (int, int, float) """ t = APc.Longitude(day, unit='cycle') return (int(t.hms.h), int(t.hms.m), t.hms.s)
def _perform(self): """ Returns an Argument() with the parameters that depend on this operation. """ self.log.info(f"Running {self.__class__.__name__} action") if self.action.args.imtype == 'OBJECT': if self.action.args.header_pointing is not None: self.log.info('Determine Moon info') site_lat = c.Latitude(self.cfg['Telescope'].getfloat('site_lat'), unit=u.degree) site_lon = c.Longitude(self.cfg['Telescope'].getfloat('site_lon'), unit=u.degree) site_elevation = self.cfg['Telescope'].getfloat('site_elevation') * u.meter loc = c.EarthLocation(site_lon, site_lat, site_elevation) pressure = self.cfg['Telescope'].getfloat('pressure', 700)*u.mbar obstime = Time(self.action.args.meta.get('date'), location=loc) altazframe = c.AltAz(location=loc, obstime=obstime, pressure=pressure) moon = c.get_moon(obstime) sun = c.get_sun(obstime) moon_alt = ((moon.transform_to(altazframe).alt).to(u.degree)).value moon_separation = (moon.separation(self.action.args.header_pointing).to(u.degree)).value\ if self.action.args.header_pointing is not None else None # Moon illumination formula from Meeus, ÒAstronomical # Algorithms". Formulae 46.1 and 46.2 in the 1991 edition, # using the approximation cos(psi) \approx -cos(i). Error # should be no more than 0.0014 (p. 316). moon_illum = 50*(1 - np.sin(sun.dec.radian)*np.sin(moon.dec.radian)\ - np.cos(sun.dec.radian)*np.cos(moon.dec.radian)\ * np.cos(sun.ra.radian-moon.ra.radian)) self.action.args.meta['moon_alt'] = moon_alt self.action.args.meta['moon_separation'] = moon_separation self.action.args.meta['moon_illum'] = moon_illum elif self.action.args.imtype == 'BIAS': self.log.info('Determine image stats') mean, med, std = stats.sigma_clipped_stats(self.action.args.ccddata.data) self.log.info(f" mean, med, std = {mean:.0f}, {med:.0f}, {std:.0f} (adu)") self.action.args.meta['mean adu'] = mean self.action.args.meta['median adu'] = med self.action.args.meta['std dev adu'] = std elif self.action.args.imtype == 'DARK': mean, med, std = stats.sigma_clipped_stats(self.action.args.ccddata.data) self.log.info(f" mean, med, std = {mean:.0f}, {med:.0f}, {std:.0f} (adu)") self.action.args.meta['mean adu'] = mean self.action.args.meta['median adu'] = med self.action.args.meta['std dev adu'] = std elif self.action.args.imtype in ['DOMEFLAT', 'TWIFLAT']: mean, med, std = stats.sigma_clipped_stats(self.action.args.ccddata.data) self.log.info(f" mean, med, std = {mean:.0f}, {med:.0f}, {std:.0f} (adu)") self.action.args.meta['mean adu'] = mean self.action.args.meta['median adu'] = med self.action.args.meta['std dev adu'] = std return self.action.args
def test_group_mixins(): """ Test grouping a table with mixin columns """ # Setup mixins idx = np.arange(4) x = np.array([3., 1., 2., 1.]) q = x * u.m lon = coordinates.Longitude(x * u.deg) lat = coordinates.Latitude(x * u.deg) # For Time do J2000.0 + few * 0.1 ns (this requires > 64 bit precision) tm = time.Time(2000, format='jyear') + time.TimeDelta(x * 1e-10, format='sec') sc = coordinates.SkyCoord(ra=lon, dec=lat) aw = table_helpers.ArrayWrapper(x) nd = np.array([(3, 'c'), (1, 'a'), (2, 'b'), (1, 'a')], dtype='<i4,|S1').view(NdarrayMixin) qt = QTable([idx, x, q, lon, lat, tm, sc, aw, nd], names=['idx', 'x', 'q', 'lon', 'lat', 'tm', 'sc', 'aw', 'nd']) # Test group_by with each supported mixin type mixin_keys = ['x', 'q', 'lon', 'lat', 'tm', 'sc', 'aw', 'nd'] for key in mixin_keys: qtg = qt.group_by(key) # Test that it got the sort order correct assert np.all(qtg['idx'] == [1, 3, 2, 0]) # Test that the groups are right # Note: skip testing SkyCoord column because that doesn't have equality for name in ['x', 'q', 'lon', 'lat', 'tm', 'aw', 'nd']: assert np.all(qt[name][[1, 3]] == qtg.groups[0][name]) assert np.all(qt[name][[2]] == qtg.groups[1][name]) assert np.all(qt[name][[0]] == qtg.groups[2][name]) # Test that unique also works with mixins since most of the work is # done with group_by(). This is using *every* mixin as key. uqt = unique(qt, keys=mixin_keys) assert len(uqt) == 3 assert np.all(uqt['idx'] == [1, 2, 0]) assert np.all(uqt['x'] == [1., 2., 3.]) # Column group_by() with mixins idxg = qt['idx'].group_by(qt[mixin_keys]) assert np.all(idxg == [1, 3, 2, 0])
def dateObs2HA(dateObs, ra, longitude=254.179722): """Returns the HA of an observation. Parameters ---------- dateObs : str An string with the TAI date at start of integration. ra : float The right ascension, in degrees, of the target. longitude : float, optional The longitude of the observatory in East degrees from 0. to 360. Returns ------- result : float The HA, in degrees, of the object at the time of the observation, rescaled between -180 to 180 degrees around the meridian. Example ------- >> dateObs = '2014-03-23T07:57:28' >> ra = 187.654 >> print(dateObs2HA(dateObs, ra)) >> 6.62507 """ if not isinstance(dateObs, basestring): raise TypeError('dateObs is not a string.') dateObs = dateObs.replace('T', ' ') dd = time.Time(dateObs, scale='tai', format='iso') lst = jd2lst(dd.jd, longitude=longitude) ha = coo.Longitude(lst.hour - ra / 15., unit=uu.hour) haDeg = ha.degree % 360 if haDeg > 180.: haDeg -= 360 return (haDeg)
def tcs_list(stars): """ Given a table of stars, ouput a list to be fed in to the TCS """ names = [] ras = [] decs = [] epoch = [] for ii,star in enumerate(stars): names.append(star['name']) ra = coord.Longitude(star['ra']*u.deg) dec = coord.Latitude(star['dec']*u.deg) ras.append(ra.to_string(unit=u.hour, sep=' ', pad=True, precision=1)) decs.append(dec.to_string(unit=u.deg, sep=' ', alwayssign=True, precision=1)) epoch.append(2000.0) t = Table() t.add_column(Column(names, name='name')) t.add_column(Column(ras, name='ra')) t.add_column(Column(decs, name='dec')) t.add_column(Column(epoch, name='epoch')) return t
def obs_info(lat_str, lon_str, elev, utc_offset): """ Create 'astropy.coord.EarthLocation' and 'astropy.time.TimezoneInfo' objects from observatoty geographical coordinates and timezone offset. Parameters ---------- lat_str : str Observatory latitude. lon_str : str Observatory longitude. elev : float Observatory elevation (in meters). utc_offset : float Observatoty timezone offset (in hours). Returns ------- tp_info : tuple Tuple with 'astropy.coord.EarthLocation' (first element) and 'astropy.time.TimezoneInfo' objetcs (second element). """ # get observatory location and timezone la = coord.Latitude(lat_str, unit=u.deg) lo = coord.Longitude(lon_str, unit=u.deg) el = u.Quantity(elev, unit=u.m) uo = u.Quantity(utc_offset, unit=u.hour) # utc offset (hours) # create earthlocation and timezoneinfo objects oloc = coord.EarthLocation(lat=la, lon=lo, height=el) otmz = TimezoneInfo(utc_offset=uo) tp_info = (oloc, otmz) return tp_info
#<-----------------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. coords.SphericalRepresentation(lon=8*u.hour, lat=5*u.deg) coords.SphericalRepresentation(lon=8*u.hourangle, lat=5*u.deg) coords.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. coords.SphericalRepresentation(coords.Longitude(8, u.hour), coords.Latitude(5, u.deg)) coords.SphericalRepresentation(coords.Longitude(8, u.hour), coords.Latitude(5, u.deg), coords.Distance(10, u.kpc)) # Arrays of any of the inputs are fine coords.SphericalRepresentation(lon=[8, 9]*u.hourangle, lat=[5, 6]*u.deg) # Default is to copy arrays, but optionally, it can be a reference coords.SphericalRepresentation(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 coords.SphericalRepresentation(lon='2h6m3.3s', lat='5rad') # Or, you can give `Quantity`s with keywords, and they will be internally # converted to Angle/Distance c1 = coords.SphericalRepresentation(lon=8*u.hourangle, lat=5*u.deg, distance=10*u.kpc)
import astropy.coordinates as asc import astropy.units as au import numpy as np """ Used https://viewer.nationalmap.gov/theme/elevation/ for the elevations """ ### BEAM_W = 23.0 * au.degree SIDE_DAY = 23.9344696 * au.hour ### LF1_LAT = asc.Latitude("26:33:19.676", unit=au.degree) LF1_LONG = asc.Longitude("-97:26:31.174", unit=au.degree) LF1_ELVF = (10.36 * au.imperial.foot).to(au.meter) LF2_LAT = asc.Latitude("34:4:43.497", unit=au.degree) LF2_LONG = asc.Longitude("-107:37:5.819", unit=au.degree) LF2_ELVF = (6967.08 * au.imperial.foot).to(au.meter) LF3_LAT = asc.Latitude("38:25:59.0", unit=au.degree) LF3_LONG = asc.Longitude("-79:50:23.0", unit=au.degree) LF3_ELVF = (2464.89 * au.imperial.foot).to(au.meter) LF4_LAT = asc.Latitude("34:12:3.0", unit=au.degree) LF4_LONG = asc.Longitude("-118:10:18.0", unit=au.degree) LF4_ELVF = (1167.89 * au.imperial.foot).to(au.meter) # Earth locations LF1 = asc.EarthLocation(LF1_LONG, LF1_LAT, LF1_ELVF) LF2 = asc.EarthLocation(LF2_LONG, LF2_LAT, LF2_ELVF) LF3 = asc.EarthLocation(LF3_LONG, LF3_LAT, LF3_ELVF) LF4 = asc.EarthLocation(LF4_LONG, LF4_LAT, LF4_ELVF)
from subprocess import check_output from datetime import datetime import astropy.coordinates as ac from astropy.time import Time, TimeDelta import astropy.units as un from delay_models import CalcReader from calcfile import make_calc # Set up times, locations, and sources. time = Time(datetime(2020, 10, 28, 15, 30, 00)) gbo_loc = ac.EarthLocation.of_site("GBT") chime_loc = ac.EarthLocation.from_geodetic(lat=ac.Latitude('49d19m15.6s'), lon=ac.Longitude('119d37m26.4s')) crab = ac.SkyCoord('05:34:31.9383', '22:00:52.175', unit=(un.hourangle, un.deg), frame='icrs') ip_peg = ac.SkyCoord("23:23:08.55", "+18:24:59.3", unit=(un.hourangle, un.deg), frame='icrs') # choose a source to use. src = crab t0 = time + TimeDelta(1, format='sec') t1 = t0.copy()
def corrections(lon, lat, alt, ra, dec, mjd): """ Calculate the heliocentric radial velocity corrections for an astronomical source. Parameters ---------- lon : `~astropy.coordinates.Longitude` or float Earth longitude of the observatory (western direction is positive). Can be anything that initialises an `~astropy.coordinates.Angle` object (if float, in degrees). lat : `~astropy.coordinates.Latitude` or float Earth latitude of observatory. Can be anything that initialises an `~astropy.coordinates.Latitude` object (if float, in degrees). alt : `~astropy.units.Quantity` or float Altitude of the observatory (if float, in meters). ra : `~astropy.coordinates.Angle` or float Right ascension of the object for epoch J2000 (if float, in degrees). dec : `~astropy.coordinates.Angle` or float Declination of the object for epoch J2000 (if float, in degrees). mjd : float The modified Julian date for the middle of exposure. Returns ------- barycorr : `~astropy.units.Quantity` The barycentric velocity correction. helcorr : `~astropy.units.Quantity` The heliocentric velocity correction. """ if not isinstance(lon, coord.Longitude): lon = coord.Longitude(lon * u.deg) if not isinstance(lat, coord.Latitude): lat = coord.Latitude(lat * u.deg) if not isinstance(alt, u.Quantity): alt *= u.m if not isinstance(ra, u.Quantity): ra *= u.deg if not isinstance(dec, u.Quantity): dec *= u.deg # Here we specify the location so that we can easily calculate the mean # local siderial time later on time = Time(2.4e6 + mjd, format="jd", location=(lon, lat, alt)) epoch = time.datetime.year + time.datetime.month/12. \ + time.datetime.day/365. # Precess the coordinates to the current epoch coordinate = coord.SkyCoord(ra, dec, frame="fk5").transform_to( coord.FK5(equinox="J%s" % (epoch))) # Convert geodetic latitude into geocentric latitude to correct for rotation # of the Earth dlat = ((-11. * 60. + 32.743) * np.sin(2 * lat) + 1.1633 * np.sin(4 * lat) \ - 0.0026 * np.sin(6 * lat)) * u.degree geocentric_lat = lat + dlat / 3600. # Calculate distance of observer from Earth center r = alt + 6378160.0 * u.m * (0.998327073 \ + 0.001676438 * np.cos(2 * geocentric_lat) \ - 0.000003510 * np.cos(4 * geocentric_lat) \ + 0.000000008 * np.cos(6 * geocentric_lat)) # Calculate rotational velocity perpendicular to the radius vector # Note: 23.934469591229 is the siderial day in hours for 1986 v = 2 * np.pi * r / (23.934469591229 * 3600 * u.second) # Calculate vdiurnal velocity time.delta_ut1_utc = 0 #we get error otherwise. No big dela for this application vdiurnal = v * np.cos(lat) * np.cos(coordinate.dec) \ * np.sin(coordinate.ra - time.sidereal_time("mean")) # Calculate baricentric and heliocentric velocities vh, vb = baryvel(time) # Project along the line of sight projection = np.array([ np.cos(coordinate.dec) * np.cos(coordinate.ra), np.cos(coordinate.dec) * np.sin(coordinate.ra), np.sin(coordinate.dec) ]) vbar = (vb * projection).sum() vhel = (vh * projection).sum() # Using baricentric velocity for correction vbar_correction = vdiurnal + vbar vhel_correction = vdiurnal + vhel # [TODO] it may be useful to return other components of velocity or extra # information about the transforms (e.g., gmst, ut, lmst, dlat, lat, vbar, # vhel, etc) return (vbar_correction, vhel_correction)
def corrections(lon, lat, alt, ra, dec, mjd, bcv_shift=None): """ Calculate the heliocentric radial velocity corrections for an astronomical source. :param lon: Earth longitude of the observatory (western direction is positive). Can be anything that initialises an `~astropy.coordinates.Angle` object (if float, in degrees). :type lon: :class:`~astropy.coordinates.Longitude` or float :param lat: Earth latitude of observatory. Can be anything that initialises an `~astropy.coordinates.Latitude` object (if float, in degrees). :type lat: :class:`~astropy.coordinates.Latitude` or float :param alt: Altitude of the observatory (if float, in meters). :type alt: :class:`~astropy.units.Quantity` or float :param ra: Right ascension of the object for epoch J2000 (if float, in degrees). :type ra: :class:`~astropy.coordinates.Angle` or float :param dec: Declination of the object for epoch J2000 (if float, in degrees). :type dec: :class:`~astropy.coordinates.Angle` or float :param mjd: The modified Julian date for the middle of exposure. :type mjd: float :returns: A two-length tuple containing the barycentric velocity correction and the heliocentric velocity correction. Both velocity corrections are given as :class:`~astropy.units.Quantity` objects. """ if not isinstance(lon, coord.Longitude): lon = coord.Longitude(lon * u.deg) if not isinstance(lat, coord.Latitude): lat = coord.Latitude(lat * u.deg) if not isinstance(alt, u.Quantity): alt *= u.m if not isinstance(ra, u.Quantity): ra *= u.deg if not isinstance(dec, u.Quantity): dec *= u.deg # Here we specify the location so that we can easily calculate the mean # local siderial time later on time = Time(2.4e6 + mjd, format="jd", location=(lon, lat, alt)) epoch = time.datetime.year + time.datetime.month/12. \ + time.datetime.day/365. # Precess the coordinates to the current epoch coordinate = coord.SkyCoord(ra, dec, frame="fk5").transform_to( coord.FK5(equinox="J{}".format(epoch))) # Convert geodetic latitude into geocentric latitude to correct for rotation # of the Earth dlat = ((-11. * 60. + 32.743) * np.sin(2 * lat) + 1.1633 * np.sin(4 * lat) \ - 0.0026 * np.sin(6 * lat)) * u.degree geocentric_lat = lat + dlat / 3600. # Calculate distance of observer from Earth center r = alt + 6378160.0 * u.m * (0.998327073 \ + 0.001676438 * np.cos(2 * geocentric_lat) \ - 0.000003510 * np.cos(4 * geocentric_lat) \ + 0.000000008 * np.cos(6 * geocentric_lat)) # Calculate rotational velocity perpendicular to the radius vector # Note: 23.934469591229 is the siderial day in hours for 1986 v = 2 * np.pi * r / (23.934469591229 * 3600 * u.second) # Calculate vdiurnal velocity try: vdiurnal = v * np.cos(lat) * np.cos(coordinate.dec) \ * np.sin(coordinate.ra - time.sidereal_time("mean")) except: logging.exception("exception in calculating vdirunal velocity") # Try again with decreased precision. time.delta_ut1_utc = 0.0 vdiurnal = v * np.cos(lat) * np.cos(coordinate.dec) \ * np.sin(coordinate.ra - time.sidereal_time("mean")) logging.warn("Explicitly set delta_ut1_utc = 0") # Calculate baricentric and heliocentric velocities vh, vb = celestial_velocities(time) # Project along the line of sight projection = np.array([ np.cos(coordinate.dec) * np.cos(coordinate.ra), np.cos(coordinate.dec) * np.sin(coordinate.ra), np.sin(coordinate.dec) ]) vbar = (vb * projection).sum() vhel = (vh * projection).sum() # Using baricentric velocity for correction # --------------------------------------------------------------------- # E. Holmbeck put this if statement in if bcv_shift != None: vbar_correction = bcv_shift else: vbar_correction = vdiurnal + vbar # --------------------------------------------------------------------- vhel_correction = vdiurnal + vhel # [TODO] it may be useful to return other components of velocity or extra # information about the transforms (e.g., gmst, ut, lmst, dlat, lat, vbar, # vhel, etc) return (vbar_correction, vhel_correction)
photspec1 = pyfits.open(photzspecname) photspec = photspec1[1].data except: photspec = 0 # read in flags inflagname = input_dir + '/flags/' + inflagtype + '.txt' outflagname = input_dir + '/flags/' + outflagtype + '.txt' flag_ind = np.loadtxt(inflagname).astype(int) flags = np.array([]) a = len(jpegname) #for i in range(1, a): for i in flag_ind: print '\nWorking on: ', incatname[i],fitsname[i],jpegname[i], i, ' of ', a print 'Coordinates of current cluster:', coord.Longitude(clust_ra[i-1], unit=u.hour).degree,coord.Latitude(clust_dec[i-1], unit=u.degree).degree #go into the class des_image(), output as c c = des_image(incatname[i],fitsname[i],jpegname[i],intracername[i], inmembername[i], inboxname[i], inbcgname[i], outbcgname[i], innotesname[i], nedspec, photspec,choose, readbcgs, xcs_zs[i-1]) if (os.path.isfile(outbcgname[i]) & owbcgs): while True: overWrite = raw_input("Would you like to (over)write the BCG file? (y/n)->") if overWrite.upper() == "Y": np.savetxt(outbcgname[i], np.transpose([np.transpose(c.bcg_ra), np.transpose(c.bcg_dec), np.transpose(c.bcg_g_mag), np.transpose(c.bcg_r_mag), np.transpose(c.bcg_i_mag), np.transpose(c.bcg_z_mag), \ np.transpose(c.bcg_gr_color),np.transpose(c.bcg_gi_color),np.transpose(c.bcg_ri_color),np.transpose(c.bcg_iz_color),np.transpose(c.bcg_rz_color)]),delimiter = ' ') break elif overWrite.upper() == "N": break else: print "Invalid Option\n"
def stack_plot_phase(spec_list, period_days, tasc_mjd=None, semiamplitude=None, mean_anomaly=None, alpha=.7, yheight=0.1, xlim=None, ylim=None, color=None, optical_phase=False): """Plot several spectra on top of each other with matplotlib. Consider also iraf.specplot('spec1,spec2,spec3'). Parameters ---------- spec_list : list of strings List of text or fits spectra extracted by extract1D (e.g., ['red0001_flux.spec.txt',red0002_flux.spec.fits']) alpha : float, default 1.0 Opacity of the plot lines yheight : float, default 0.1 Proportion of phase 0-1 to scale the range of each spectrum to. optical_phase : boolean, default False if False, use TASC as phase zero point; else use TASC-0.25 """ category20 = N.array([ '#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#dbdb8d', '#17becf', '#9edae5' ]) sb.set_style('white') # sb.set_palette(sb.dark_palette(color, n_colors = len(spec_list)), # n_colors=len(spec_list)) mpl.rcParams['xtick.labelsize'] = 14 mpl.rcParams['ytick.labelsize'] = 14 mpl.rcParams['axes.labelsize'] = 16 mpl.rcParams['font.size'] = 16 mpl.rcParams['legend.fontsize'] = 14 atm_bands = [ [6701, 6715], # dome overhead lamp flourescence feature [6860, 7000], [7570, 7700], [7150, 7350], [8100, 8401] ] # trim a funky bin with +1 def exclude_bands(wave, bands): winband = N.zeros(len(wave)).astype(N.bool) for band in bands: winband |= ((wave >= band[0]) & (wave <= band[1])) #woutband = ~winband return winband phases = [] xs = [] ys = [] labels = [] mjds = [] for spec in spec_list: if spec.endswith('txt'): dat = N.genfromtxt(spec, names='wave, flux', dtype='f4, f4') raise ValueError('Need fits spectra') elif spec.endswith('fits'): hdulist = pyfits.open(spec) hdr = hdulist[0].header flux = hdulist[0].data crpix1 = hdr['CRPIX1'] crval1 = hdr['CRVAL1'] cd1_1 = hdr['CDELT1'] mjd = hdr['MJD'] spec_length = len(flux) wave = cd1_1 * (N.arange(spec_length) - (crpix1 - 1)) + crval1 dat = {'wave': wave, 'flux': flux} P200_loc = coord.EarthLocation(lat=coord.Latitude('33d21m21.6s'), lon=coord.Longitude('-116d51m46.80s'), height=1706.) t = BaryTime(mjd, format='mjd', scale='utc', location=P200_loc) PSR_coords = coord.SkyCoord(322.43776, -4.48521, frame='icrs', unit=u.deg) bjd_tdb = t.bcor(PSR_coords).mjd phase = mjd_to_phase(bjd_tdb, period_days, tasc_mjd=tasc_mjd)[0] # for j2129: convert to optical phase convention tasc_phase = phase if optical_phase: phase = (phase - 0.25) % 1 if xlim is None: wmin = 0 else: wmin = N.nonzero(wave > xlim[0])[0][0] offset_val = N.median(dat['flux'][wmin:wmin + 100]) pct = N.percentile(dat['flux'], [5, 95]) scale_val = yheight / (pct[1] - pct[0]) w = exclude_bands(wave, atm_bands) dat['flux'][w] = N.NaN # correct for the binary shift if (semiamplitude is not None) and (mean_anomaly is not None): predicted_shift = mean_anomaly - semiamplitude * \ N.cos(2.*N.pi * tasc_phase) # delta_lambda/lambda_emitted = v/c in nonrel. case # so lambda_emitted = lambda_obs/ (1+v/c) dat['wave'] = dat['wave'] / (1 + predicted_shift / 299792.458) mjds.append(mjd) phases.append(phase) xs.append(dat['wave']) ys.append((dat['flux'] - offset_val) * scale_val + phase) labels.append(spec) mjds_set = N.sort(N.unique(N.floor(mjds))) assert (len(mjds_set) < len(category20)) if color is None: colors = category20[[ N.where(mjds_set == N.floor(mi))[0][0] for mi in mjds ]] else: colors = [color for mi in mjds] fig = plt.figure(figsize=(20, 8)) ax = plt.subplot(111) args = N.argsort(phases) for i in args: print(labels[i], phases[i]) plt.plot(xs[i], ys[i], label=labels[i], alpha=alpha, linewidth=1., color=colors[i]) plt.xlabel("Wavelength (Angstrom)") plt.ylabel("Orbital Phase (cycles)") if xlim is not None: plt.xlim(xlim) if ylim is not None: plt.ylim(ylim) #plt.legend() sb.despine() plt.show() return ax
'tm': tm, 'tm2': tm2, 'tm3': tm3, 'dt': time.TimeDelta([1, 2] * u.day), 'sc': sc, 'scd': scd, 'scdc': scdc, 'scpm': scpm, 'scpmrv': scpmrv, 'scrv': scrv, 'x': [1, 2] * u.m, 'qdb': [10, 20] * u.dB(u.mW), 'qdex': [4.5, 5.5] * u.dex(u.cm / u.s**2), 'qmag': [21, 22] * u.ABmag, 'lat': coordinates.Latitude([1, 2] * u.deg), 'lon': coordinates.Longitude([1, 2] * u.deg, wrap_angle=180. * u.deg), 'ang': coordinates.Angle([1, 2] * u.deg), 'el': el, 'sr': sr, 'cr': cr, 'sd': sd, 'srd': srd, 'nd': table.NdarrayMixin([1, 2]), 'obj': obj, } time_attrs = [ 'value', 'shape', 'format', 'scale', 'precision', 'in_subfmt', 'out_subfmt', 'location' ] compare_attrs = { 'tm':
def test___init__(self) -> None: """Test method ``__init__``. Copying from astropy docs """ # ----------- c = icoord.InterpolatedSkyCoord( [10] * self.num, [20] * self.num, unit="deg", affine=self.affine, ) # defaults to ICRS frame self._test_isc(c) # ----------- c = icoord.InterpolatedSkyCoord( [1, 2, 3, 4], [-30, 45, 8, 16], frame="icrs", unit="deg", affine=self.affine[:4], ) # 4 coords self._test_isc(c) # ----------- coords = [ "1:12:43.2 +31:12:43", "1:12:43.2 +31:12:43", "1:12:43.2 +31:12:43", "1 12 43.2 +31 12 43", ] c = icoord.InterpolatedSkyCoord( coords, frame=coord.FK4, unit=(u.hourangle, u.deg), obstime="J1992.21", affine=self.affine[:4], ) self._test_isc(c) # ----------- c = icoord.InterpolatedSkyCoord( ["1h12m43.2s +1d12m43s"] * self.num, frame=coord.Galactic, affine=self.affine, ) # Units from string self._test_isc(c) # # ----------- c = icoord.InterpolatedSkyCoord( frame="galactic", l=["1h12m43.2s"] * self.num, b="+1d12m43s", # NOT BROADCASTING THIS ONE affine=self.affine, ) self._test_isc(c) # ----------- ra = coord.Longitude([1, 2, 3, 4], unit=u.deg) # Could also use Angle dec = np.array([4.5, 5.2, 6.3, 7.4]) * u.deg # Astropy Quantity c = icoord.InterpolatedSkyCoord( ra, dec, frame="icrs", affine=self.affine[:4], ) self._test_isc(c) # ----------- c = icoord.InterpolatedSkyCoord( frame=coord.ICRS, ra=ra, dec=dec, obstime="2001-01-02T12:34:56", affine=self.affine[:4], ) self._test_isc(c) # ----------- c = coord.FK4( [1] * self.num * u.deg, 2 * u.deg, ) # Uses defaults for obstime, equinox c = icoord.InterpolatedSkyCoord( c, obstime="J2010.11", equinox="B1965", affine=self.affine, ) # Override defaults self._test_isc(c) # ----------- c = icoord.InterpolatedSkyCoord( w=[0] * self.num, u=1, v=2, unit="kpc", frame="galactic", representation_type="cartesian", affine=self.affine, ) self._test_isc(c, representation_type=coord.CartesianRepresentation) # ----------- c = icoord.InterpolatedSkyCoord( [ coord.ICRS(ra=1 * u.deg, dec=2 * u.deg), coord.ICRS(ra=3 * u.deg, dec=4 * u.deg), ] * (self.num // 2), affine=self.affine, ) self._test_isc(c)
def dat2hdf5(table_dir): """ Convert the Marshall et al. (2006) map from \*.dat.gz to \*.hdf5. """ import astropy.io.ascii as ascii import gzip from contextlib import closing readme_fname = os.path.join(table_dir, 'ReadMe') table_fname = os.path.join(table_dir, 'table1.dat.gz') h5_fname = os.path.join(table_dir, 'marshall.h5') # Extract the gzipped table with gzip.open(table_fname, 'rb') as f: # Read in the table using astropy's CDS table reader r = ascii.get_reader(ascii.Cds, readme=readme_fname) r.data.table_name = 'table1.dat' # Hack to deal with bug in CDS reader. table = r.read(f) print(table) # Reorder table entries according to Galactic (l, b) l = coordinates.Longitude(table['GLON'][:], wrap_angle=180. * units.deg) b = table['GLAT'][:] sort_idx = np.lexsort((b, l)) l = l[sort_idx].astype('f4') b = b[sort_idx].astype('f4') l.shape = (801, 81) b.shape = (801, 81) # Extract arrays from the table chi2_all = np.reshape((table['x2all'][sort_idx]).astype('f4'), (801, 81)) chi2_giants = np.reshape((table['x2gts'][sort_idx]).astype('f4'), (801, 81)) A = np.empty((801 * 81, 33), dtype='f4') sigma_A = np.empty((801 * 81, 33), dtype='f4') dist = np.empty((801 * 81, 33), dtype='f4') sigma_dist = np.empty((801 * 81, 33), dtype='f4') for k in range(33): A[:, k] = table['ext{:d}'.format(k + 1)][sort_idx] sigma_A[:, k] = table['e_ext{:d}'.format(k + 1)][sort_idx] dist[:, k] = table['r{:d}'.format(k + 1)][sort_idx] sigma_dist[:, k] = table['e_r{:d}'.format(k + 1)][sort_idx] A.shape = (801, 81, 33) sigma_A.shape = (801, 81, 33) dist.shape = (801, 81, 33) sigma_dist.shape = (801, 81, 33) # Construct the HDF5 file h5_fname = os.path.join(table_dir, 'marshall.h5') filter_kwargs = dict( chunks=True, compression='gzip', compression_opts=3, # scaleoffset=4 ) with h5py.File(h5_fname, 'w') as f: dset = f.create_dataset('A', data=A, **filter_kwargs) dset.attrs['description'] = 'Extinction of each bin' dset.attrs['band'] = 'Ks (2MASS)' dset.attrs['units'] = 'mag' dset = f.create_dataset('sigma_A', data=sigma_A, **filter_kwargs) dset.attrs['description'] = 'Extinction uncertainty of each bin' dset.attrs['band'] = 'Ks (2MASS)' dset.attrs['units'] = 'mag' dset = f.create_dataset('dist', data=dist, **filter_kwargs) dset.attrs['description'] = 'Distance of each bin' dset.attrs['units'] = 'kpc' dset = f.create_dataset('sigma_dist', data=sigma_dist, **filter_kwargs) dset.attrs['description'] = 'Distance uncertainty of each bin' dset.attrs['units'] = 'kpc' dset = f.create_dataset('chi2_all', data=chi2_all, **filter_kwargs) dset.attrs['description'] = 'Chi^2, based on all the stars' dset.attrs['units'] = 'unitless' dset = f.create_dataset('chi2_giants', data=chi2_giants, **filter_kwargs) dset.attrs['description'] = 'Chi^2, based on giants only' dset.attrs['units'] = 'unitless' # filter_kwargs.pop('scaleoffset') dset = f.create_dataset('l', data=l, **filter_kwargs) dset.attrs['description'] = 'Galactic longitude' dset.attrs['units'] = 'deg' dset = f.create_dataset('b', data=b, **filter_kwargs) dset.attrs['description'] = 'Galactic latitude' dset.attrs['units'] = 'deg'
from astropy import constants as const from astropy import units as u from astropy.utils.iers import IERS from astropy.utils.iers import IERS_A, IERS_A_URL from astropy.utils.data import download_file from astropy.io import ascii from astropy import coordinates as coord from astropy import _erfa as erfa import numpy as np import warnings # mean sidereal rate (at J2000) in radians per (UT1) second SR = 7.292115855306589e-5 P48_loc = coord.EarthLocation(lat=coord.Latitude('33d21m26.35s'), lon=coord.Longitude('-116d51m32.04s'), height=1707.) def barycenter_times(mjds, ra, dec, loc=P48_loc): # use built-in barycentering in astropy 1.2+ t = time.Time(mjds, format='mjd', scale='utc', location=loc) obj_coords = coord.SkyCoord(ra, dec, frame='icrs', unit=u.deg) ltt_bary = t.light_travel_time(obj_coords) time_barycentre = t.tdb + ltt_bary return time_barycentre.mjd def prev_barycenter_times(mjds, ra, dec, loc=P48_loc):
"""Constants.""" import os import inspect import numpy as np from astropy.time import Time import astropy.coordinates as coords import astropy.units as u import astroplan BASE_DIR = os.path.dirname( os.path.abspath(inspect.getfile(inspect.currentframe()))) + '/' P48_loc = coords.EarthLocation(lat=coords.Latitude('33d21m26.2s'), lon=coords.Longitude('-116d51m35.5s'), height=1707.) # use UTC only P48_Observer = astroplan.Observer(location=P48_loc) # HA and Dec from http://www.oir.caltech.edu/twiki_oir/bin/view/Palomar/ZTF/TelescopeSpecifications v5 # Dome estimate from Jeff Z email, 9/21/15 # goals info from Jeff Z email, 12/12/16 # Ha/Dec from Telescope Drive Performance Assessment v1.2; dome estimate from # Jeff Z. email, 9/27/17 P48_slew_pars = { 'ha': { 'coord': 'ra', 'accel': 0.4 * u.deg * u.second**(-2.), 'decel': 0.4 * u.deg * u.second**(-2.), 'vmax': 2.5 * u.deg / u.second
return request.param # Fixture to run all tests for both an unmasked (ndarray) and masked # (MaskedArray) column. @pytest.fixture(params=[False, True]) def table_type(request): return MaskedTable if request.param else table.Table # Stuff for testing mixin columns MIXIN_COLS = { 'quantity': [0, 1, 2, 3] * u.m, 'longitude': coordinates.Longitude([0., 1., 5., 6.] * u.deg, wrap_angle=180. * u.deg), 'latitude': coordinates.Latitude([5., 6., 10., 11.] * u.deg), 'time': time.Time([2000, 2001, 2002, 2003], format='jyear'), 'skycoord': coordinates.SkyCoord(ra=[0, 1, 2, 3] * u.deg, dec=[0, 1, 2, 3] * u.deg), 'sphericalrep': coordinates.SphericalRepresentation([0, 1, 2, 3] * u.deg, [0, 1, 2, 3] * u.deg, 1 * u.kpc), 'cartesianrep': coordinates.CartesianRepresentation([0, 1, 2, 3] * u.pc, [4, 5, 6, 7] * u.pc, [9, 8, 8, 6] * u.pc), 'sphericaldiff': coordinates.SphericalCosLatDifferential([0, 1, 2, 3] * u.mas / u.yr,
def correct_rvs_homebrew(savfile='bestfitvels.sav', outfile='test_rv_vlsr.txt', observatory='Palomar'): """take output of getvel.pro and correct to solar system barycenter requires all observations to come from the same observatory""" sav = readsav(savfile, python_dict=True) minchi2 = sav['minchi2fit'] fitvels = sav['fitvels'] velerrs = sav['velerrs'] exptimes = sav['exptime'] if len(minchi2.shape) == 2: (ntemplates, nobs) = minchi2.shape wbest = minchi2.argmin(axis=0) best_vel = fitvels[wbest, N.arange(nobs)] best_err = velerrs[wbest, N.arange(nobs)] else: nobs = minchi2.shape[0] ntemplates = 1 best_vel = fitvels best_err = velerrs #intermediate_file = 'rv.obs' #f = open(intermediate_file,'w') f = open(outfile, 'w') f.write("# BJD_TDB EXPTIME VLSR VERR VSYS\n") sys_errs = [] for i, obsfile in enumerate(sav['observations'].tolist()): velocity = best_vel[i] if observatory == 'Palomar': # DBSP spectra reduced by my pipeline hdulist = pyfits.open(obsfile + '.spec.fits') hdr = hdulist[0].header ra = hdr['RA'] dec = hdr['DEC'] sys_velerr = hdr[ 'VERR'] # velocity error do to wavelength uncertainty sys_errs.append(sys_velerr) obs_mid = find_midpoint_time(hdr) tel_loc = coord.EarthLocation( lat=coord.Latitude('33d21m21.6s'), lon=coord.Longitude('-116d51m46.80s'), height=1706.) t = BaryTime(obs_mid, format='datetime', scale='utc', location=tel_loc) elif observatory == 'Keck': # LRIS spectra reducd by Dan Perley's pipeline sys_errs.append(0.) rahms = get_dperley_header(obsfile + '.spec', 'RA').strip().strip("'") decdms = get_dperley_header(obsfile + '.spec', 'DEC').strip().strip("'") c = coord.SkyCoord(ra=rahms, dec=decdms, unit=(u.hourangle, u.deg)) ra = c.ra.value dec = c.dec.value exptime = get_dperley_header( obsfile + '.spec', 'EXPTIME', converter=N.float) * u.second mjd = get_dperley_header( obsfile + '.spec', 'MJD-OBS', converter=N.float) * u.day tel_loc = coord.EarthLocation( lat=coord.Latitude('19d49m34.9s'), lon=coord.Longitude('-155d28m30.04s'), height=4145.) t = BaryTime(mjd + exptime / 2., format='mjd', scale='utc', location=tel_loc) else: raise NotImplementedError( 'Observatory {} not implemented'.format(observatory)) PSR_coords = coord.SkyCoord(ra, dec, frame='icrs', unit=u.deg) (h_pos, h_vel, b_pos, b_vel) = t._obs_pos() m, vect = t._vect(PSR_coords) v_corr = (b_vel.dot(vect) * const.au / (1 * u.day)).to(u.km / u.s) bjd_tdb = t.bcor(PSR_coords).jd f.write('{} {} {} {:.2f} {}\n'.format(bjd_tdb[0], exptimes[i], best_vel[i] + v_corr.value[0], best_err[i], sys_errs[i])) f.close()