# 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'), 'timedelta': time.TimeDelta([1, 2, 3, 4], format='jd'), '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,
import os import pkg_resources import numpy as np import pickle as pkl import astropy.time as at import astropy.coordinates as asc import astropy.units as au import scipy.interpolate as sin """ EarthLocations taken from [email protected]/pulsar_search """ 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) class LoFASM_Station (object): """Models LoFASM station coordinate systems and stuff"""
mixin_cols = { '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, 'su': su, 'su2': su2, } time_attrs = [ 'value', 'shape', 'format', 'scale', 'precision', 'in_subfmt', 'out_subfmt', 'location'
import numpy as np from astropy.time import Time import astropy.coordinates as coords import astropy.units as u import astroplan P48_loc = coords.EarthLocation(lat=coords.Latitude('33d21m26.35s'), lon=coords.Longitude('-116d51m32.04s'), height=1707.) # use UTC only P48_Observer = astroplan.Observer(location=P48_loc) P48_slew_pars = { 'ha': { 'coord': 'ra', 'accel': 0.27 * u.deg * u.second**(-2.), 'decel': 0.27 * u.deg * u.second**(-2.), 'vmax': 1.6 * u.deg / u.second }, 'dec': { 'coord': 'dec', 'accel': 0.2 * u.deg * u.second**(-2.), 'decel': 0.15 * u.deg * u.second**(-2.), 'vmax': 1.2 * u.deg / u.second }, 'dome': { 'coord': 'az', 'accel': 0.17 * u.deg * u.second**(-2.), 'decel': 0.6 * u.deg * u.second**(-2.), 'vmax': 3. * u.deg / u.second
def corrections(lon, lat, alt, ra, dec, mjd): """ 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 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 time_latitude(): coordinates.Latitude(3.2, units.degree)
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 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.0 + jd jd = time.Time(jd, format="jd") 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 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
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()