def main(): ts = load.timescale() t = ts.tt(2018, 1, 22, 9, 9, 20) trial_angles = 10, 20, 30, 40 # the error peaks around 20 degrees trial_elevations = 0, 6000, AU_M print(__doc__) for n in range(1, 5): print('=== {} iterations ==='.format(n)) print('') for elevation_m in trial_elevations: for degrees in trial_angles: top = Topos(latitude_degrees=degrees, longitude_degrees=123, elevation_m=elevation_m) xyz_au = top.at(t).position.au xyz_au = einsum('ij...,j...->i...', t.M, xyz_au) lat, lon, elev = reverse_terra(xyz_au, t.gast, n) lat = lat / DEG2RAD error_mas = 60.0 * 60.0 * 1000.0 * abs(degrees - lat) print('latitude {} degrees, elevation {} m' ' -> error of {:.2f} mas' .format(degrees, elevation_m, error_mas)) print('') print("""\ Given that iterations=3 pushes the maximum error from tens of mas ("mas" means " milli-arcsecond") down to hundredths of a mas, it is the value we have chosen as a default. A fourth iteration, if we ever chose to perform one, pushes the error down to "0.00 mas". """)
def test_earth_deflection(): # The NOVAS library includes the Earth's gravitational deflection of # light for both topocentric observers and observers in Earth orbit, # but shuts this effect off once the object is behind the Earth 20% # of the way from its limb towards its center. This test determines # whether Skyfield puts the resulting discontinuity in the same # place as the NOVAS library does. # # For more details see: # https://github.com/skyfielders/astronomy-notebooks/blob/master/Skyfield-Notes/Fixing-earth-deflection.ipynb t = load.timescale(delta_t=0.0) t = t.tt(2016, 7, 2, arange(10.5628, 10.5639, 0.0002)) planets = load('de405.bsp') earth = planets['earth'] mars = planets['mars'] lowell = earth + Topos(latitude_degrees=35.2029, longitude_degrees=-111.6646) ra, dec, distance = lowell.at(t).observe(mars).apparent().radec() h = ra.hours hprime = diff(h) assert hprime[0] > 1.8e-8 assert hprime[1] > 1.8e-8 assert hprime[2] < 1.3e-8 # moment when nadir angle crosses 0.8 assert hprime[3] > 1.8e-8 assert hprime[4] > 1.8e-8
def compute_flight_time(planets, start_name, destination_name, g): start = planets[start_name + ' barycenter'] destination = planets[destination_name + ' barycenter'] ts = load.timescale() t = ts.now() astrometric = start.at(t).observe(destination) distance = astrometric.distance().km acceleration = acceleration_g_to_km_sec_sqr(g) time_of_flight = flip_and_burn(acceleration, distance) return time_of_flight
def get_next_pass(satellite, satellite_name): # Create a time vector of 24 hours ts = load.timescale() current = datetime.datetime.now() minutes = range(current.minute, 60 * 24 + current.minute) t = ts.utc(current.year, current.month, current.day, current.hour, \ minutes) orbit = (satellite - GROUND_STATION).at(t) alt, az, distance = orbit.altaz() above_horizon = alt.degrees > 0 boundaries, = np.diff(above_horizon).nonzero() passes = boundaries.reshape(len(boundaries) // 2, 2) if len(passes) > 0: return passes[0] else: print("Error, no passes found for {}".format(satellite_name)) sys.exit(2)
def calc_radec_w_proper_motion(ra, de, pmra, pmde, epoch=2018.): planets = load('/Users/gks/Dropbox/mypylib/notebooks/GIT/HETobs/de421.bsp') ts = load.timescale() earth = planets['earth'] t = ts.utc(epoch) t_2000 = ts.utc(2000) ra_ang = Angle(degrees=ra) de_ang = Angle(degrees=de) star_obj = Star(ra=ra_ang, dec=de_ang, ra_mas_per_year=pmra, dec_mas_per_year=pmde) astrometric = earth.at(t).observe(star_obj) ra_out, dec_out, dist_out = astrometric.radec() ra_new = ra_out.to(u.degree).value de_new = dec_out.to(u.degree).value print("Old:", ra, de) print("New:", ra_new, de_new) return ra_new, de_new
def plotear_planetas(self): planetas = load('de421.bsp') #Cargando planetas self.earth, venus, sun, mercury, neptune, mars, saturn, jupyter, uranus, moon = planetas[ 'earth'], planetas['venus'], planetas['sun'], planetas[ 1], planetas[8], planetas['mars'], planetas[6], planetas[ 5], planetas[7], planetas['moon'] ts = load.timescale() t = ts.utc(self.fecha_hora.replace(tzinfo=utc)) self.graficar_planeta(venus, t, 'Venus') self.graficar_planeta(mercury, t, 'Mercurio') self.graficar_planeta(mars, t, 'Marte') self.graficar_planeta(saturn, t, 'Saturno') self.graficar_planeta(jupyter, t, 'Jupiter') self.graficar_planeta(neptune, t, 'Neptuno') self.graficar_planeta(sun, t, 'Sol') self.graficar_planeta(moon, t, 'Luna') self.graficar_planeta(uranus, t, 'Urano')
def greatest_elevation_schedule(ordered_events, location): pass_T = 120. # length of minimum pass in seconds exposure_T = 20. # length of exposure buffer_T = 40. + exposure_T # time between exposures ts = load.timescale() site = wgs84.latlon(location[0], location[1], elevation_m=0) ccd_schedule = [] jSec = 1.0 / 24 / 60 / 60 # second in julian time for event in ordered_events: elevations = list() for tdx, t in enumerate(np.linspace(event[1], event[2], 100)): difference = event[0] - site elevations.append(difference.at(ts.tt_jd(tdx)).elevation) event.append(event[1] + (event[2]-event[1])/100*elevations.index(max(elevations)))
def main(): print('Skyfield version: {0}'.format(skyfield.__version__)) print('jplephem version: {0}'.format(version_of('jplephem'))) print('sgp4 version: {0}'.format(version_of('sgp4'))) ts = load.timescale() fmt = '%Y-%m-%d' final_leap = (ts._leap_tai[-1] - 1) / (24 * 60 * 60) print('Built-in leap seconds table ends with leap second at: {0}'.format( ts.tai_jd(final_leap).utc_strftime())) arrays = load_bundled_npy('iers.npz') daily_tt = arrays['tt_jd_minus_arange'] daily_tt += np.arange(len(daily_tt)) start = ts.tt_jd(daily_tt[0]) end = ts.tt_jd(daily_tt[-1]) print('Built-in ∆T table from finals2000A.all covers: {0} to {1}'.format( start.utc_strftime(fmt), end.utc_strftime(fmt)))
def main(): ## get the global parameters global wcs, imgSize, refUTC, imgScale, mwa, ts, line1, line2, line3 hdu = fits.open( str(args.obs) + "-" + str(args.midName) + "-1-0000-dirty.fits") wcs = WCS(hdu[0].header, naxis=2) imgSize = hdu[0].header["NAXIS1"] imgScale = np.abs(hdu[0].header["CDELT2"]) refUTC = datetime.strptime(hdu[0].header["DATE-OBS"], '%Y-%m-%dT%H:%M:%S.%f') ## get the relevant tle for the satellite line1, line2, line3 = obtainTLE(args.noradid) if args.debug: print("line1 {0}\nline2 {1}\nline3 {2}".format(line1, line2, line3)) mwa = Topos("26.701276778 S", "116.670846137 E", elevation_m=377.827) ts = load.timescale() intrack_offset_array = np.linspace(-10, 10, 10) offtrack_offset_array = np.linspace(-0.5, 0.5, 10) all_combinations = [(a, b) for a in intrack_offset_array for b in offtrack_offset_array] waterfall = np.zeros((10, 10, args.channels)) for f in tqdm(range(args.channels)): if args.debug: print("working on channel {}".format(f)) global utc_array, cube utc_array, cube = getCube(f) with multiprocessing.Pool(processes=28) as pool: results = pool.starmap(worker, all_combinations) results = np.array(results) waterfall[:, :, f] = results.reshape((10, 10)) np.save( str(args.noradid) + "-" + str(args.obs) + "waterfall.npy", waterfall)
def ccd_schedule(schedule, location): """ Creates a schedule for use with and external Parameters: schedule: location: Returns: """ # user inputs pass_T = 120. # length of minimum pass in seconds exposure_T = 20. # length of exposure buffer_T = 40. + exposure_T # time between passes # predefinition ts = load.timescale() site = wgs84.latlon(float(location[0]), float(location[1])) ccd_schedule = [] jSec = 1.0 / 24 / 60 / 60 # second in julian time # add first event, assuming first event is long enough event = schedule[0] difference = event[0] - site ccd_schedule.append([event[0], event[1], event[1] + buffer_T * jSec]) ccd_schedule[0].extend([difference.at(ts.tt_jd(ccd_schedule[0][1] + exposure_T / 2. * jSec)), difference.at(ts.tt_jd(ccd_schedule[0][2] + exposure_T / 2. * jSec))]) for event in schedule[1:]: if event[1] - buffer_T * jSec > ccd_schedule[-1][2] \ and event[2] > ccd_schedule[-1][2] + (buffer_T + pass_T) * jSec: difference = event[0] - site ccd_schedule.append([event[0], max(ccd_schedule[-1][2] + buffer_T*jSec, event[1])]) ccd_schedule[-1].append(ccd_schedule[-1][1] + buffer_T * jSec) ccd_schedule[-1].extend([difference.at(ts.tt_jd(ccd_schedule[-1][1] + exposure_T / 2.*jSec)), difference.at(ts.tt_jd(ccd_schedule[-1][2] + exposure_T / 2.*jSec))]) return ccd_schedule
def run(): rospy.init_node('sun_seeker_node', anonymous=True) rospy.Subscriber('/clock', Clock, sim_time_callback) pub = rospy.Publisher('/sun_seeker/vector', Vector3, queue_size=1) rate = rospy.Rate(0.1) eph = load('de421.bsp') sun = eph['sun'] moon = eph['moon'] path = os.path.realpath(__file__) pc = PlanetaryConstants() pc.read_text(load('moon_080317.tf')) pc.read_text(load('pck00008.tpc')) pc.read_binary(load('moon_pa_de421_1900-2050.bpc')) frame = pc.build_frame_named('MOON_ME_DE421') place = moon + pc.build_latlon_degrees(frame, -86.79430, -21.18640) sun_angle_msg = Vector3() while not rospy.is_shutdown(): dt = datetime.fromtimestamp(sim_time) dt_utc = dt.replace(tzinfo=pytz.UTC) ts = load.timescale() t = ts.from_datetime(dt_utc) sunpos = place.at(t).observe(sun).apparent() alt, az, distance = sunpos.altaz() sun_angle_msg.x = 0.0 sun_angle_msg.y = alt.degrees sun_angle_msg.z = az.degrees if rospy.get_time() - last_msg_time < msg_timeout: rospy.loginfo('Publishing vector: x = {0:.3f}, y = {1:.3f}, z = {2:.3f}'.format(sun_angle_msg.x, sun_angle_msg.y, sun_angle_msg.z)) pub.publish(sun_angle_msg) else: rospy.logwarn('Timeout {0:.1f} seconds: Is /clock publishing?'.format(msg_timeout)) rate.sleep()
def hour_angle(self, object_ra: float, object_dec: float, date=None): """ Converts the provided right ascension (RA) of an object to its corresponding hour angle (HA), based on the provided date. Args: date: Desired date for the calculation of the hour angle object_ra (float): The right ascension of the object in J2000 object_dec (float): Object's declination in J2000 Todo: Check the reason that the the values for the HA differ by almost 2 minutes from the real ones Todo: Also add a solid documentation for the whole file, explaining in detail the parsed arguments Todo: Update the docstring of this function because there is a major change. Returns: float: Calculated hour angle """ if date is None: date = self.current_time() else: if len(date) == 3: day = int(date[2]) hour = (date[2] - day) * 24 minute = (hour - int(hour)) * 60 second = int(minute - int(minute)) * 60 date = (date[0], date[1], day, int(hour), int(minute), second) object_coordinates = SkyCoord(ra=str(object_ra), dec=str(object_dec), unit='deg') equinox_time = Time(datetime.datetime(*date), scale='utc', location=self.location, format='datetime') ra_jnow = object_coordinates.transform_to(FK5(equinox=equinox_time)).ra # Get the local sidereal time time_scale = load.timescale() utc_time = time_scale.utc(*date) local_sidereal_time = utc_time.gast * 15 + self.location.lon.degree return round(local_sidereal_time - ra_jnow.degree, 6) # Return the calculated hour angle
def sun_earth_distance(date): """ Input: - UTC datetime object Output: - Sun-Earth distance (meters) """ planets = load('de421.bsp') earth, sun = planets['earth'], planets['sun'] ts = load.timescale() t = ts.utc(date.replace(tzinfo=utc)) astrometric = earth.at(t).observe(sun) ra, dec, distance = astrometric.radec() return distance.m
def _convert_radec_to_altaz(ra, dec, lon, lat, height, time): """Convert a single position. This is done for easy code sharing with other tools. Skyfield does support arrays of positions. """ radec = Star(ra=Angle(degrees=ra), dec=Angle(degrees=dec)) earth = load(EPHEMERIS)['earth'] location = earth + Topos(longitude_degrees=lon, latitude_degrees=lat, elevation_m=height * 1000.0) ts = load.timescale() obstime = ts.from_astropy(Time(time, scale='utc')) alt, az, _ = location.at(obstime).observe(radec).apparent().altaz(pressure_mbar=0) return dict(az=az.degrees, alt=alt.degrees)
def generate_report(self): # the tricky bits to get look angles for a list of times ts = load.timescale(builtin=True) # get rid of the milliseconds in there truth = ts.now().utc now_ish = ts.utc(truth[0],truth[1],truth[2],truth[3],truth[4],truth[5]) now = now_ish.tt # make an arry with times incremented by really close to 30 sec # this looks weird since it is terrestrial time floating point run_time = arange(now, now + .5, .000347222) # feed that array to the time function as julian days t = ts.tt(jd=run_time) # spit out the positon and vector of our location astrometric = self.ant.at(t).observe(self.name).apparent() # convert this to alt and az lists alt, az, distance = astrometric.altaz() t_list = t.utc_strftime('%Y:%m:%d:%H:%M:%S') alt_list = alt.degrees.tolist() az_list = az.degrees.tolist() self.report = [] self.rise_time = None self.fade_time = None for idx,item in enumerate(t_list): if alt_list[idx] < 10.0: continue else: if self.rise_time is None: self.rise_time = t_list[idx] self.fade_time = t_list[idx] az_out = "{:.4f}".format(az_list[idx]) alt_out = "{:.4f}".format(alt_list[idx]) output = t_list[idx]+", "+az_out+", "+alt_out+"\n" self.report.append(output)
def get_servo(lat, lng, sat_name, timestamp): ts = load.timescale() lines = get_sat(sat_name) line1 = lines[0] line2 = lines[1] current_time = timestamp my_position = Topos(lat, lng) satellite = EarthSatellite(line1, line2, sat_name, ts) difference = satellite - my_position data = "" for i in range(720): dt_object = datetime.utcfromtimestamp(current_time) dt_object = dt_object.replace(tzinfo=utc) t = ts.utc(dt_object) topocentric = difference.at(t) alt, az, distance = topocentric.altaz() alt_d = alt.degrees az_d = az.degrees if (az_d > 180): alt_d = flit_alt(alt_d) az_d = az_d - 180 if (az_d < 0): alt_d = flit_alt(alt_d) az_d = 180 + az_d # print(current_time,az_d,alt_d) data += str(current_time) + ', ' + str( translate(az_d, 0, 180, 2457, 7372)) + ", " + str( translate(alt_d, 0, 180, 2457, 7372)) + '\n' current_time += 1 return data
def search(self, sat, lat, long, timeStart, timeEnd, tolerance): """ Returns the time for which a satellite is over the given coordinates within the time range given :param satellite sat: The satellite of interest :param float lat: The latitude of the search point :param float lon: The longitude of the search point :param datetime timeStart: The beginning of the time range to search through :param datetime timeEnd: The end of the time range to search through :param float tolerance: How close a satellite needs to the point (in km) :returns: The time at which the satellite is over the given coordinates. Returns None if not found :rtype: datetime """ self.satellite = self.satellites[sat.name] # Calculate orbital period n = float(sat.meanMotion) mu = 398600; # km^3/s^2 a = mu**(1/3) / (2*n*pi/86400)**(2/3) T = 2*pi*(a**3/mu)**(1/2) # Determine dt ts = load.timescale() dt = timedelta(seconds = T/100) # Search for time t = timeStart while t <= timeEnd: currentTime = ts.utc(t.year, t.month, t.day, t.hour, t.minute, t.second) geocentric = self.satellite.at(currentTime) subpoint = geocentric.subpoint() currentLat = subpoint.latitude.degrees currentLong = subpoint.longitude.degrees if(haversine((lat, long), (currentLat, currentLong)) < tolerance): return t t = t + dt # If nothing found return None return None
def test_radec_and_altaz_angles_and_rates(): # HORIZONS test data in Skyfield repository: authorities/radec-altaz-rates ts = load.timescale() t = ts.utc(2021, 2, 3) top = wgs84.latlon(35.1844866, 248.347300, elevation_m=2106.9128) planets = load('de421.bsp') a = (planets['earth'] + top).at(t).observe(planets['mars']).apparent() # First, verify RA and declination. frame = framelib.true_equator_and_equinox_of_date dec, ra, distance, dec_rate, ra_rate, range_rate = ( a.frame_latlon_and_rates(frame)) arcseconds = 3600.0 assert abs((ra.degrees - 40.75836) * arcseconds) < 0.04 assert abs((dec.degrees - 17.16791) * arcseconds) < 0.005 assert abs(distance.m - 1.21164331503552 * AU_M) < 120.0 # Verify RA and declination rates of change. assert round(dec_rate.arcseconds.per_hour, 5) == 25.61352 assert round(ra_rate.arcseconds.per_hour * cos(dec.radians), 4) == round(75.15571, 4) # TODO: get last digit to agree? assert abs(range_rate.km_per_s - 16.7926932) < 2e-5 # Verify altitude and azimuth. frame = top alt, az, distance, alt_rate, az_rate, range_rate = ( a.frame_latlon_and_rates(frame)) assert round(alt.degrees, 4) == 65.2758 assert round(az.degrees, 4) == 131.8839 assert abs(distance.m - 1.21164331503552 * AU_M) < 120.0 # Verify altitude and azimuth rates of change. assert abs(range_rate.km_per_s - 16.7926932) < 2e-5 assert round(alt_rate.arcseconds.per_minute, 2) == 548.66 assert round(az_rate.arcseconds.per_minute * cos(alt.radians), 2) == 663.55
def __init__(self): self.gps = load.tle_file("https://celestrak.com/NORAD/elements/gps-ops.txt") self.galileo = load.tle_file("https://celestrak.com/NORAD/elements/galileo.txt") self.glonass = load.tle_file("https://celestrak.com/NORAD/elements/glo-ops.txt") self.beidou = load.tle_file("https://celestrak.com/NORAD/elements/beidou.txt") self.allsat = self.gps+self.galileo+self.glonass+self.beidou print('Loaded', len(self.allsat), 'satellites') # create dict where we can fetch a satellite using its name as key self.sats_by_name = {sat.name: sat for sat in self.allsat} # Define observatory for az,el calculation self.obs = Topos('57.393109 N', '11.917798 E') # OSO25m # Define timerange, https://rhodesmill.org/skyfield/time.html self.ts = load.timescale() self.tgps = False self.tgalileo = False self.tglonass = False self.tbeidou = False #self.sat2plot = self.gps+self.galileo self.sat2plot = [] # Plot the data, awaiting key-press events self.plot()
def get_range_velocity(sat_name: str, obs_lat: float, obs_lon: float, time: datetime) -> typing.List[float]: ts = load.timescale() if isinstance(time, str): time = parse(time) time = time.replace(tzinfo=utc) time = ts.utc(time) if time is not None else ts.now() observer = Topos(obs_lat, obs_lon) stations_url = "http://celestrak.com/NORAD/elements/stations.txt" satellites = load.tle(stations_url) sat = satellites[sat_name] relative_position = (sat - observer).at(time) # sat_velocity = sat.at(tnow).velocity.km_per_s range_velocity = relative_position.velocity.km_per_s return range_velocity
def getSatMWA(line1, line2, line3): """ creates a satellite object and observer object Paramters --------- line1 : tle line 1 line2 : tle line 2 line3 : tle line 3 Returns ------- satellite : the sat object mwa : the observer object ts : the time object """ ts = load.timescale(builtin=True) satellite = EarthSatellite(line2, line3, line1, ts) mwa = Topos("26.701276778 S", "116.670846137 E", elevation_m= 377.827) return satellite, mwa, ts
def test_using_elevation_to_locate_center_of_moon(): # Test the `elevation_m` parameter by using it to offset a Moon # surface location back to the Moon's center. ts = load.timescale() t = ts.utc(2020, 4, 23) eph = load('de421.bsp') a1 = eph['moon'].at(t) pc = PlanetaryConstants() pc.read_text(load('moon_080317.tf')) pc.read_text(load('pck00008.tpc')) pc.read_binary(load('moon_pa_de421_1900-2050.bpc')) frame = pc.build_frame_named('MOON_ME_DE421') place = pc.build_latlon_degrees(frame, 26.3, 313.2, -1737400) a2 = (eph['moon'] + place).at(t) mm = 1e-3 assert max(abs(a1.position.m - a2.position.m)) < mm
def get_adcs_vectors(time_data, tle_data): sun = JPL_EPH['sun'] earth = JPL_EPH['earth'] ts = load.timescale() label="Satellite" satellite = EarthSatellite(tle_data["line_1"], tle_data["line_2"], label, ts) time_instant = ts.utc( time_data["year"], time_data["month"], time_data["day"], time_data["hour"], time_data["min"], time_data["sec"], ) tru_pos = earth + satellite sun_vector1 = tru_pos.at(time_instant).observe(sun).apparent().position.km sun_vector2 = satellite.at(time_instant).position.km # sun_vector = satellite.at(time_instant).observe(earth).apparent() # print(tru_pos.at(time_instant).position.km) # print(earth.at(time_instant).position.km) return [sun_vector1 - sun_vector2]
def test_minor_planet(): text = (b'00001 3.4 0.15 K205V 162.68631 73.73161 80.28698' b' 10.58862 0.0775571 0.21406009 2.7676569 0 MPO492748' b' 6751 115 1801-2019 0.60 M-v 30h Williams 0000 ' b'(1) Ceres 20190915\n') ts = load.timescale() t = ts.utc(2020, 6, 17) eph = load('de421.bsp') df = mpc.load_mpcorb_dataframe(BytesIO(text)) row = df.iloc[0] assert row.designation_packed == '00001' assert row.designation == '(1) Ceres' ceres = mpc.mpcorb_orbit(row, ts, GM_SUN) ra, dec, distance = eph['earth'].at(t).observe(eph['sun'] + ceres).radec() assert ceres.target == '(1) Ceres' assert abs(ra.hours - 23.1437) < 0.00005 assert abs(dec.degrees - -17.323) < 0.0005
def hour_angle_to_ra(self, object_ha: float, object_dec: float, date=None): """ Convert the provided object's hour angle to its corresponding right ascension. This method assumes that ephem is properly calibrated. Also the date is assumed to be now. Todo: Check what happens in every case and if the conversion of degrees is needed Args: object_ha (float): Hour angle of the desired object object_dec (float): Declination of the object date (tuple): The desired date Returns: The current right ascension of the object in J2000 """ # Get the local sidereal time if date is None: date = self.current_time() # Get the current time and date as needed else: if len(date) == 3: day = int(date[2]) hour = (date[2] - day)*24 minute = (hour - int(hour))*60 second = int(minute - int(minute))*60 date = (date[0], date[1], day, int(hour), int(minute), second) # Calculate the desired right ascension time_scale = load.timescale() utc_time = time_scale.utc(*date) local_sidereal_time = utc_time.gast * 15 + self.location.lon.degree calculated_ra = local_sidereal_time - object_ha # Calculate the right ascension in JNOW # Calculate the right ascension of the provided object in J2000 equinox_time = Time(datetime.datetime(*date), scale='utc', location=self.location, format='datetime') object_coordinates = SkyCoord(ra=str(calculated_ra), dec=str(object_dec), unit='deg', frame=FK5, equinox=equinox_time) ra_j2000 = object_coordinates.transform_to(FK5(equinox='J2000.0')).ra return round(ra_j2000.degree, 6)
def compare_obj(planets, code, year, month, day, hour=0, minute=0, second=0): ''' compare position between jpl query and skyfield computation parameters: ---------- code : 1,2,3,4,5,6,7,8,9,10,199,299,399,301 year: int, month: int, day: int, hour: int default 0, minute: int default 0, second float default 0, ''' # print(code) ts = load.timescale() t = ts.utc(year, month, day, hour, minute, second) objname = planets.names()[code][0] # print(objname) obj = planets[objname] icrf_sf = obj.at(t) # print(icrf_sf.position) icrf_sf_np = icrf_sf.position.km time = Time(t.utc_iso()) times = time.tt+np.linspace(0, 1, 2)*u.s objquery = Horizons(id=str(code), id_type='majorbody', location='@0', epochs={'start': times.value[0], 'stop': times.value[1], 'step': '1'}) icrf_jpl = objquery.vectors(refplane='earth') icrf_jpl['x'].convert_unit_to('km') icrf_jpl['y'].convert_unit_to('km') icrf_jpl['z'].convert_unit_to('km') icrf_jpl_np = np.array( [icrf_jpl['x'][0], icrf_jpl['y'][0], icrf_jpl['z'][0]]) print(objname + ' icrf_sf_np in km', icrf_sf_np) print(objname + ' icrf_jpl_np in km', icrf_jpl_np) print(objname + ' icrf_sf_np-icrf_jpl_np in km', icrf_sf_np-icrf_jpl_np) print()
def test_against_horizons(): # See the following files in the Skyfield repository: # # horizons/ceres-orbital-elements # horizons/ceres-position ts = load.timescale(builtin=True) t = ts.tdb_jd(2458886.500000000) a = 2.768873850275102E+00 # A e = 7.705857791518426E-02 # EC p_au = a * (1 - e**2) # Wikipedia k = KeplerOrbit.from_mean_anomaly( p=Distance(au=p_au), # see above e=e, i=Angle(degrees=2.718528770987308E+01), Om=Angle(degrees=2.336112629072238E+01), w=Angle(degrees=1.328964361683606E+02), M=Angle(degrees=1.382501360489816E+02), epoch=t, #? mu_km_s=None, mu_au_d=2.9591220828559093E-04, center=None, target=None, center_name=None, target_name=None, ) r, v = k._at(t)[:2] sun_au = [ -0.004105894975783999, 0.006739680703224941, 0.002956344702049446, ] horizons_au = [ 1.334875927366032E+00, -2.239607658161781E+00, -1.328895183461897E+00, ] assert max(abs(r + sun_au - horizons_au)) < 2e-15
def sat_separations(params): ''' Separation between a source and set of satellites. Parameters ---------- params: list [[source_ra, source_dec], date] source_ra: float Right Ascension of source in radians. source_dec: float Declination of source in radians. date: datetime Date and time of observation. Returns ------- separations: array Angular separation between each satellite and the source in degrees. ''' source, t = params source_ra, source_dec = source satellites = get_sat_tles() ts = load.timescale() tt = ts.utc(*[int(x) for x in t.strftime('%Y %m %d %H %M %S').split()]) mkat = Topos('30.7130 S', '21.4430 E') separations = np.zeros((len(satellites.items()))) for j, sat in enumerate(satellites.items()): sat_ra, sat_dec = [(sat[1]-mkat).at(tt).radec(ts.J2000)[i].radians for i in range(2)] separations[j] = np.rad2deg(angular_separation(sat_ra, sat_dec, [source_ra, source_dec])) return separations
def readTLE(fileName='./india_tle.dat'): # tle referesh days refresh_days = 14 # current date and time ts = load.timescale(builtin=True) t = ts.now() days = 1 if not os.path.exists(fileName): # call create local tle function print("Creating new tle file") dict = getISROSatelliteList() saveTLE(dict, fileName) # load the new one satellites = load.tle(fileName) else: # load the local file satellites = load.tle(fileName) # get the first in the dictionary sat_id = list(satellites.keys())[0] satellite = satellites[sat_id] days = t - satellite.epoch # if older than refresh_days create new local tle and load new one if abs(days) > refresh_days: # call create local tle function print("Creating new tle file") dict = getISROSatelliteList() saveTLE(dict, fileName) # load the new one satellites = load.tle(fileName) # sats dictionary for easy search sats = {} for item in [satellites]: names = [key for key in item.keys()] for satname in names: sat = item[satname] satid = sat.model.satnum sats[satid] = sat sats[satname] = sat # return dictionary return sats
def readTLE(fileName='./india_tle.dat'): # tle referesh days refresh_days = 14 # current date and time ts = load.timescale(builtin=True) t = ts.now() days = 1 old_date = 0 # call create local tle function print("Creating new tle file") dict = getISROSatelliteList() saveTLE(dict, fileName) # load the new one satellites = load.tle(fileName) if abs(days) > refresh_days: # call create local tle function print("Creating new tle file") # backup old tle backupFilename = Path(fileName).stem + old_date + '.dat' os.rename(fileName, backupFilename) # get the new one dict = getISROSatelliteList() saveTLE(dict, fileName) # load the new one satellites = load.tle(fileName) # sats dictionary for easy search sats = {} for item in [satellites]: names = [key for key in item.keys()] for satname in names: sat = item[satname] satid = sat.model.satnum sats[satid] = sat sats[satname] = sat # return dictionary return sats
def hip_position(hip_nr, temperature=15, pressure=1005): """ Returns uncorrected and refraction corrected apparent positions of stars in the Hipparcos catalogue. Position is specified to Waltz observer. """ #Load list of planets and specify to earth to get obersver, then specify to location of Waltz planets = load('de421.bsp') earth = planets['earth'] waltz = earth + Topos( '49.3978620896919 N', '8.724700212478638 E', elevation_m=562.0) #Load current time. ts = load.timescale() t = ts.now() #t=t.utc #Convert #Load star catalogue coordinates from hipparcos.py module star = hipparcos.get(hip_nr) #Compute astrometric and apparent coordinates for Waltz at time t astrometric = waltz.at(t).observe(star) apparent = astrometric.apparent() #Change to alt, az coordinates to compute refraction correction, then change back again #Change Temp and pressure alt, az, distancealt = apparent.altaz(temperature_C=temperature, pressure_mbar=pressure) corrected = apparent.from_altaz(alt=alt, az=az) #RA,DEC,Dist of refraction corrected positions ra_calc, dec_calc, distance = corrected.radec() #RA,DEC,Dist of refraction uncorrected positions ra_calc_without_refraction, dec_calc_without_refraction, distance = apparent.radec( epoch='date') return [ ra_calc, dec_calc, ra_calc_without_refraction, dec_calc_without_refraction ]
def _get_times(self, now: datetime) -> (datetime, datetime): midnight = now.replace(hour=0, minute=0, second=0, microsecond=0) next_midnight = midnight + timedelta(days=1) ts = load.timescale() t0 = ts.from_datetime(midnight) t1 = ts.from_datetime(next_midnight) eph = load_file(config['DE421_PATH']) bluffton = wgs84.latlon(config['COORDINATES']['N'] * N, config['COORDINATES']['E'] * E) f = almanac.dark_twilight_day(eph, bluffton) times, events = almanac.find_discrete(t0, t1, f) result = [] previous_e = None for t, e in zip(times, events): if e == 4: result.append(t.astimezone(self.zone)) if previous_e == 4: result.append(t.astimezone(self.zone)) previous_e = e return result[0], result[1]
def rise_and_set_time(self, satellite): """ Accepts a satellite, returns the next rise and set time for that satellite as a tuple of datetimes """ # create skyfield latlon loc = wgs84.latlon(self.lat, self.lon) # create timescale ts = load.timescale() t0, t1 = ts.from_datetimes(self.time_window(1)) # get events where satellite reaches altitude at location in time window times, _ = satellite.find_events( loc, t0, t1, altitude_degrees=self.altitude_degrees) # get rise and sent time for first event rise_time = times[0].utc_datetime() set_time = times[2].utc_datetime() return (rise_time, set_time)
def test_vectors(): ts = load.timescale() t = ts.tt(2017, 1, 23, 10, 44) planets = load('de421.bsp') earth = planets['earth'] mars = planets['mars'] v = earth assert str(v) == """\ Sum of 2 vectors: + Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 3 EARTH BARYCENTER + Segment 'de421.bsp' 3 EARTH BARYCENTER -> 399 EARTH""" assert repr(v) == "\ <VectorSum of 2 vectors 0 SOLAR SYSTEM BARYCENTER -> 399 EARTH>" assert str(v.at(t)) == "\ <Barycentric position and velocity at date t center=0 target=399>" v = earth - mars assert str(v) == """\ Sum of 4 vectors: - Segment 'de421.bsp' 4 MARS BARYCENTER -> 499 MARS - Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 4 MARS BARYCENTER + Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 3 EARTH BARYCENTER + Segment 'de421.bsp' 3 EARTH BARYCENTER -> 399 EARTH""" assert repr(v) == "\ <VectorSum of 4 vectors 499 MARS -> 399 EARTH>" assert str(v.at(t)) == "\ <Geometric position and velocity at date t center=499 target=399>" geocentric = Geocentric([0,0,0]) assert geocentric.center == 399
def __init__(self, lg=None,obs=None,refraction_method=None): # self.lg=lg self.name='SF Skyfield' self.obs_astropy=obs self.refraction_method=refraction_method longitude,latitude,height=self.obs_astropy.to_geodetic() # positive values are used for eastern longitudes # ToDo # print(type(height)) # print(str(height)) # 3236.9999999999477 m # print(height.meter) # AttributeError: 'Quantity' object has no 'meter' member elevation=float(str(height).replace('m','').replace('meter','')) earth = planets['earth'] # N +, E + hurray self.obs=earth.topos( latitude_degrees=latitude.degree, longitude_degrees=longitude.degree, elevation_m=elevation, ) self.ts=load.timescale()
def archived_tle(): """ Return a list of HST TLEs from space-track https://www.space-track.org/basicspacedata/query/class/tle/EPOCH/2015-01-01--2016-12-31/NORAD_CAT_ID/20580/orderby/TLE_LINE1%20ASC/format/tle HST_TLE.txt: https://www.space-track.org/basicspacedata/query/class/tle/EPOCH/2009-08-01--2016-12-31/NORAD_CAT_ID/20580/orderby/TLE_LINE1%20ASC/format/tle """ from skyfield.api import load from skyfield.constants import AU_KM import astropy.time ts = load.timescale() eph = load('de421.bsp') earth = eph['earth'] #sat = earth.satellite('\n'.join(lines)) #lines = open('2015-16_TLEs.txt').readlines() #lines = open('HST_TLE.txt').readlines() lines = open('HST_TLE_WFC3.txt').readlines() lines = [line.strip() for line in lines] N = len(lines)//2 times = [] strings = [] for i in range(N): print(i,N) tle_str = 'HST\n'+'\n'.join(lines[i*2:i*2+2]) sat = earth.satellite(tle_str) t0 = astropy.time.Time(sat.epoch.utc_datetime()) times.append(t0.mjd) strings.append(tle_str) return np.array(times), np.array(strings)
def test_positions_skyfield(): """ Test positions against those generated by skyfield. """ t = Time('1980-03-25 00:00') location = None # skyfield ephemeris planets = load('de421.bsp') ts = load.timescale() mercury, jupiter, moon = planets['mercury'], planets['jupiter barycenter'], planets['moon'] earth = planets['earth'] skyfield_t = ts.from_astropy(t) if location is not None: earth = earth.topos(latitude_degrees=location.latitude.to(u.deg).value, longitude_degrees=location.longitude.to(u.deg).value, elevation_m=location.height.to(u.m).value) skyfield_mercury = earth.at(skyfield_t).observe(mercury).apparent() skyfield_jupiter = earth.at(skyfield_t).observe(jupiter).apparent() skyfield_moon = earth.at(skyfield_t).observe(moon).apparent() if location is not None: obsgeoloc, obsgeovel = location.get_gcrs_posvel(t) frame = GCRS(obstime=t, obsgeoloc=obsgeoloc, obsgeovel=obsgeovel) else: frame = GCRS(obstime=t) ra, dec, dist = skyfield_mercury.radec(epoch='date') skyfield_mercury = SkyCoord(ra.to(u.deg), dec.to(u.deg), distance=dist.to(u.km), frame=frame) ra, dec, dist = skyfield_jupiter.radec(epoch='date') skyfield_jupiter = SkyCoord(ra.to(u.deg), dec.to(u.deg), distance=dist.to(u.km), frame=frame) ra, dec, dist = skyfield_moon.radec(epoch='date') skyfield_moon = SkyCoord(ra.to(u.deg), dec.to(u.deg), distance=dist.to(u.km), frame=frame) moon_astropy = get_moon(t, location) mercury_astropy = get_body(t, 'mercury', location) jupiter_astropy = get_body(t, 'jupiter', location) # convert to true equator and equinox jupiter_astropy = _apparent_position_in_true_coordinates(jupiter_astropy) mercury_astropy = _apparent_position_in_true_coordinates(mercury_astropy) moon_astropy = _apparent_position_in_true_coordinates(moon_astropy) assert (moon_astropy.separation(skyfield_moon) < skyfield_angular_separation_tolerance) assert (moon_astropy.separation_3d(skyfield_moon) < skyfield_separation_tolerance) assert (jupiter_astropy.separation(skyfield_jupiter) < skyfield_angular_separation_tolerance) assert (jupiter_astropy.separation_3d(skyfield_jupiter) < skyfield_separation_tolerance) assert (mercury_astropy.separation(skyfield_mercury) < skyfield_angular_separation_tolerance) assert (mercury_astropy.separation_3d(skyfield_mercury) < skyfield_separation_tolerance)
def __init__(self, observer, time_list): self.earth = self._createearth() self.ts = load.timescale() self.time = self._createdatearray(time_list) self.obs = self._createobs(observer)
def predictStorms(startdate, predictdays, includeonlyiorelatedFlag, calcinterval, modeflag): global ts, iterDateUTCtime, th, L3, U1, modeset, JupiterRise, JupiterSet, SunRise, SunSet, includeonlyiorelated, predList modeset = modeflag includeonlyiorelated = includeonlyiorelatedFlag planets = load('de421.bsp') earthPlanet = planets['earth'] inidt = datetime.strptime(startdate, '%Y%m%d') ts = load.timescale() initDateUTC = ts.utc(inidt.year, inidt.month, inidt.day, 0.0, 0.0, 0.0 ).utc_datetime() #print("initDateUTC: ", initDateUTC, type(initDateUTC)) ephemObsPos = ephem.Observer() if radioConfig.stationLat[-1:] == "S": lonSign = "-" else: lonSign = "" ephemObsPos.lat = lonSign + radioConfig.stationLat[0:-2] ephemObsPos.lon = radioConfig.stationLon[0:-2] ephemObsPos.elev = radioConfig.stationElev #To get U.S. Naval Astronomical Almanac values, use these settings ephemObsPos.pressure= 0 # set the horizon that you want to use to one that is exactly 34 arcminutes lower # than the normal horizon, to match the value by which the Navy reckons that # an object at the horizon is refracted: ephemObsPos.horizon = '-0:34' myposition = earthPlanet + Topos(radioConfig.stationLat, radioConfig.stationLon) print("pyephem observer position: ", ephemObsPos) print("myposition: ", myposition) # 1) the central meridian longitude of Jupiter that faces us # 2) the position of the inner-most moon Io in its orbit around Jupiter L3 = 0 U1 = 0 th = 0.0 predList = [] iterDateUTC = initDateUTC finalDateUTC = initDateUTC + timedelta(days=(predictdays-1)) #external loop on requested days: while iterDateUTC < finalDateUTC: ephemObsPos.date = (iterDateUTC + + timedelta(hours=12) ).strftime('%Y-%m-%d %H:%M:%S') JupiterRise = ephem2datetime(str(ephemObsPos.previous_rising(ephem.Jupiter()))) JupiterSet = ephem2datetime(str(ephemObsPos.next_setting (ephem.Jupiter()))) JupiterNextRise = ephem2datetime(str(ephemObsPos.next_rising(ephem.Jupiter()))) SunRise = ephem2datetime(str(ephemObsPos.next_rising(ephem.Sun()))) SunSet = ephem2datetime(str(ephemObsPos.next_setting(ephem.Sun()))) #internal loop within a single day iterDateUTCtime = iterDateUTC endOfDayUTCtime = iterDateUTC + timedelta(days=1) while iterDateUTCtime < endOfDayUTCtime: #this way i will do the other calcs only when Jupiter is above the local horizon and the Sun is not visible: if ((iterDateUTCtime > JupiterRise and iterDateUTCtime < JupiterSet) or iterDateUTCtime > JupiterNextRise ) and (iterDateUTCtime < SunRise or iterDateUTCtime > SunSet): calcforjd() #calculate again every N minutes: iterDateUTCtime = iterDateUTCtime + timedelta(minutes=calcinterval) # since we have covered this day, let's go on with the next one: iterDateUTC = iterDateUTC + timedelta(days=1) return predList
#!/usr/bin/env python from skyfield.positionlib import ICRF from skyfield.api import load,Topos ts=load.timescale() t=ts.now() observer=Topos(latitude_degrees=52.8344,longitude_degrees=6.3785,elevation_m=10.0) p=ICRF([0.0,0.0,0.0],observer_data=observer,t=t) q=p.from_altaz(alt_degrees=30.0,az_degrees=30.0) print(p,q)
def ts(): yield load.timescale()
# this source is part of my Hackster.io project: https://www.hackster.io/mariocannistra/radio-astronomy-with-rtl-sdr-raspberrypi-and-amazon-aws-iot-45b617 # this program will output the Jupiter-IO radio storm predictions in text format. # It's a port to python of an older QBasic program whose original source can be found # at http://www.spaceacademy.net.au/spacelab/projects/jovrad/jovrad.htm together with # good explanations about the theory and instructions to build a folded dipole antenna. import raforpi from skyfield.api import load import sys from datetime import datetime, timedelta from pytz import timezone import radioConfig from dateutil.relativedelta import relativedelta # the section below needs deeper check on the involved formulas: print('\nJovicentric Declination of Earth: (to be checked)') eph = load('jup310.bsp') jupiter = eph['jupiter'] earth = eph['earth'] deyear = 2000 while deyear < 2020: initDateUTC = load.timescale().utc(deyear, 1, 1, 0.0, 0.0, 0.0 ) geometry = jupiter.at( initDateUTC ).observe(earth) jcera, jcedec, jcedist = geometry.radec() jcinfo = 'year {}\tjcedec {}'.format( initDateUTC.utc_datetime().strftime('%Y%m%d'), jcedec ) print(jcinfo) deyear = deyear + 1