class Lookup: vectors = None elements = None def __init__(self, id, idType, relativeTo, time=Time.now()): self.obj = Horizons(id=id, id_type=idType, location=relativeTo, epochs=time.jd) def mass(self): if self.elements is None: self.elements = self.obj.elements(get_raw_response=True) match = _massPattern.search(self.elements) if match: n, m = match.group(1), match.group(2) kg = float(f'{m}e{n}') return kg * units.kilogram return None def vectorData(self, columnName): if self.vectors is None: self.vectors = self.obj.vectors() return self.vectors[columnName].quantity[0] def position(self): return CartesianRepresentation(self.vectorData('x'), self.vectorData('y'), self.vectorData('z')) def velocity(self): return CartesianRepresentation(self.vectorData('vx'), self.vectorData('vy'), self.vectorData('vz')) def assignTo(self, celestialTurtle): celestialTurtle.mass = self.mass() celestialTurtle.setposition(self.position()) celestialTurtle.setvelocity(self.velocity())
def get_horizons_positioning(self, entity_id, observer_id): obj = Horizons(id=entity_id, location='@{}'.format(observer_id), epochs=Time(self.date).jd, id_type='id') if not entity_id == observer_id: vectors = obj.vectors() elements = obj.elements() # get the eccentricity (e) and semimajor axis (a) e = elements['e'].data[0] a = elements['a'].data[0] name = elements['targetname'].data[0].replace('Barycenter ', '') # get the components of position and velocity from JPL SSD x, y = vectors['x'], vectors['y'] vx, vy = vectors['vx'], vectors['vy'] speed = math.hypot(vx, vy) # calculate angle of velocity by finding the tangent to the orbit # pygame specific: horizontally reflect the angle due to reversed y-axis angle = math.pi - ((2 * math.pi) - math.atan2(y, x)) return x, y, speed, angle, e, a, name else: # special case for the central body of a system (e.g. the sun) # obj.elements() does not work for when entity_id and observer_id are the same name = obj.vectors()['targetname'].data[0].replace( 'Barycenter ', '') return 0, 0, 0, 0, 0, 0, name
def query(self, term, location=None, start=None, end=None, step=None): if all((start, end, step)): epochs = {'start': start, 'end': end, 'step': step} else: epochs = None try: obj = Horizons(id=term, location=location, epochs=epochs) self.catalog_data = obj.elements() except (ValueError, IOError): self.catalog_data = {}
def getHorizonsElements( obj_ids, times, location="@sun", id_type="smallbody" ): """ Query JPL Horizons (through astroquery) for an object's elements at the given times. Parameters ---------- obj_ids : `~numpy.ndarray` (N) Object IDs / designations recognizable by HORIZONS. times : `~astropy.core.time.Time` Astropy time object at which to gather state vectors. location : str, optional Location of the origin typically a NAIF code. ('0' or '@ssb' for solar system barycenter, '10' or '@sun' for heliocenter) [Default = '@sun'] id_type : {'majorbody', 'smallbody', 'designation', 'name', 'asteroid_name', 'comet_name', 'id'} ID type, Horizons will find closest match under any given type. Returns ------- elements : `~pandas.DataFrame` Dataframe containing the full cartesian state, r, r_rate, delta, delta_rate and light time of the object at each time. """ _checkTime(times, "times") dfs = [] for obj_id in obj_ids: obj = Horizons( id=obj_id, epochs=times.tdb.mjd, location=location, id_type=id_type, ) elements = obj.elements( refsystem="J2000", refplane="ecliptic", tp_type="absolute", cache=False ).to_pandas() dfs.append(elements) elements = pd.concat(dfs) elements.reset_index( inplace=True, drop=True ) return elements
def _query_horizons(self) -> None: """Takes the object name from the text box, queries Horizons, and fills the RA/Dec inputs with the result.""" from astroquery.jplhorizons import Horizons # query try: obj = Horizons(id=self.textHorizonsName.text(), location=None, epochs=Time.now().jd) # result = MPC.get_ephemeris(, location=self.observer.location) except InvalidQueryError: QtWidgets.QMessageBox.critical(self, "MPC", "No result found") return print(obj) print(obj.uri) try: eph = obj.elements() except ValueError: pass print(eph) print(eph.columns) print(obj.uri) self.spinOrbitElementsEcc.setValue(eph["e"][0]) self.spinOrbitElementsIncl.setValue(eph["incl"][0]) self.spinOrbitElementsSemiMajorAxis.setValue(eph["a"][0]) self.spinOrbitElementsMA.setValue(eph["M"][0]) self.spinOrbitElementsOmega.setValue(eph["Omega"][0]) self.spinOrbitElementsPerifocus.setValue(eph["w"][0]) self.spinOrbitElementsEpoch.setValue(eph["datetime_jd"][0]) return # to coordinates coord = SkyCoord.guess_from_table(result)[0] # set it self.textTrackRA.setText(coord.ra.to_string(u.hour, sep=":")) self.textTrackDec.setText(coord.dec.to_string(sep=":"))
def get_elems(obj_id, start): ''' Parameters ---------- obj_id : `str` Number of asteroid, defined by MPC. start : `str` Beginning time of integration, UTC. Returns ------- el_jpl : `~numpy.ndarray` (N, 12) Orbital elements as returned by jpl, first column is obj_id. ''' epochs = ap.time.Time(start).jd el_obj = Horizons(id=obj_id, location='500@10', epochs=epochs) el_jpl = el_obj.elements() el_jpl['targetname'] = obj_id return el_jpl
def get_planet(self, n): """ Nth planet info. Parameters: n: planet number (Mercury is 1, etc.) Returns: Tuple consisting of the r0: current coordinates (AU) orbit: calculated orbit name: name of the planet """ obj = Horizons(id=n, location="@sun", epochs=self.__t0, id_type='id') r0 = np.array([float(obj.vectors()[xn]) for xn in ['x', 'y', 'z']]) v = np.array([float(obj.vectors()[xn]) for xn in ['vx', 'vy', 'vz']]) r = np.copy(r0) tmax = np.double(obj.elements()['P']) # orbital period (days) dt = tmax / 400 # seems like an OK compromise between accuracy and performance orbit = compute_orbit(r, v, dt, tmax) name = obj.vectors()['targetname'].data[0].split()[ 0] # extracts the name of planet return r0, orbit, name
def from_horizons(cls, targetids, id_type='smallbody', epochs=None, center='500@10', **kwargs): """Load target orbital elements from `JPL Horizons <https://ssd.jpl.nasa.gov/horizons.cgi>`_ using `astroquery.jplhorizons.HorizonsClass.elements` Parameters ---------- targetids : str or iterable of str Target identifier, i.e., a number, name, designation, or JPL Horizons record number, for one or more targets. id_type : str, optional The nature of ``targetids`` provided; possible values are ``'smallbody'`` (asteroid or comet), ``'majorbody'`` (planet or satellite), ``'designation'`` (asteroid or comet designation), ``'name'`` (asteroid or comet name), ``'asteroid_name'``, ``'comet_name'``, ``'id'`` (Horizons id). Default: ``'smallbody'`` epochs : `~astropy.time.Time` or dict, optional Epochs of elements to be queried; requires a `~astropy.time.Time` object with a single or multiple epochs. A dictionary including keywords ``start`` and ``stop``, as well as either ``step`` or ``number``, can be used to generate a range of epochs. ``start`` and ``stop`` have to be `~astropy.time.Time` objects (see :ref:`epochs`). If ``step`` is provided, a range of epochs will be queries starting at ``start`` and ending at ``stop`` in steps of ``step``; ``step`` has to be provided as a `~astropy.units.Quantity` object with integer value and a unit of either minutes, hours, days, or years. If ``number`` is provided as an integer, the interval defined by ``start`` and ``stop`` is split into ``number`` equidistant intervals. If ``None`` is provided, current date and time are used. All epochs should be provided in TDB; if not, they will be converted to TDB and a `~sbpy.data.TimeScaleWarning` will be raised. Default: ``None`` center : str, optional, default ``'500@10'`` (center of the Sun) Elements will be provided relative to this position. **kwargs : optional Arguments that will be provided to `astroquery.jplhorizons.HorizonsClass.elements`. Notes ----- * For detailed explanations of the queried fields, refer to `astroquery.jplhorizons.HorizonsClass.elements` and the `JPL Horizons documentation <https://ssd.jpl.nasa.gov/?horizons_doc>`_. * By default, elements are provided in the J2000.0 reference system and relative to the ecliptic and mean equinox of the reference epoch. Different settings can be chosen using additional keyword arguments as used by `astroquery.jplhorizons.HorizonsClass.elements`. Returns ------- `~Orbit` object Examples -------- >>> from sbpy.data import Orbit >>> from astropy.time import Time >>> epoch = Time('2018-05-14', scale='tdb') # doctest: +REMOTE_DATA >>> eph = Orbit.from_horizons('Ceres', epochs=epoch) # doctest: +REMOTE_DATA """ # modify epoch input to make it work with astroquery.jplhorizons # maybe this stuff should really go into that module.... if epochs is None: epochs = [Time.now().tdb.jd] elif isinstance(epochs, Time): if epochs.scale != 'tdb': warn(('converting {} epochs to tdb for use in ' 'astroquery.jplhorizons').format(epochs.scale), TimeScaleWarning) epochs = epochs.tdb.jd elif isinstance(epochs, dict): if 'start' in epochs and 'stop' in epochs and 'number' in epochs: epochs['step'] = epochs['number']*u.dimensionless_unscaled # convert to tdb and iso for astroquery.jplhorizons epochs['start'] = epochs['start'].tdb.iso epochs['stop'] = epochs['stop'].tdb.iso if 'step' in epochs: if epochs['step'].unit is not u.dimensionless_unscaled: epochs['step'] = '{:d}{:s}'.format( int(epochs['step'].value), {u.minute: 'm', u.hour: 'h', u.d: 'd', u.year: 'y'}[epochs['step'].unit]) else: epochs['step'] = '{:d}'.format( int(epochs['step'].value-1)) # if targetids is a list, run separate Horizons queries and append if not isinstance(targetids, (list, ndarray, tuple)): targetids = [targetids] # append elements table for each targetid all_elem = None for targetid in targetids: # load elements using astroquery.jplhorizons obj = Horizons(id=targetid, id_type=id_type, location=center, epochs=epochs) try: elem = obj.elements(**kwargs) except ValueError as e: raise QueryError( ('Error raised by astroquery.jplhorizons: {:s}\n' 'The following query was attempted: {:s}').format( str(e), obj.uri)) # workaround for current version of astroquery to make # column units compatible with astropy.table.QTable # should really change '---' units to None in # astroquery.jplhorizons.__init__.py for column_name in elem.columns: if elem[column_name].unit == '---': elem[column_name].unit = None if all_elem is None: all_elem = elem else: all_elem = vstack([all_elem, elem]) # turn epochs into astropy.time.Time and apply timescale # https://ssd.jpl.nasa.gov/?horizons_doc all_elem['epoch'] = Time(all_elem['datetime_jd'], format='jd', scale='tdb') all_elem['Tp'] = Time(all_elem['Tp_jd'], format='jd', scale='tdb') all_elem.remove_column('datetime_jd') all_elem.remove_column('datetime_str') all_elem.remove_column('Tp_jd') return cls.from_table(all_elem)
def ephemeris(desg, epochs, orbit=True): """Ephemeris and orbital parameters. Parameters ---------- desg : string Object designation. epochs : array-like or dictionary `epochs` parameter for `astroquery.jplhorizons.Horizons`. orbit : bool, optional Set to `False` to exclude orbital parameters. Returns ------- eph : astropy.table.Table All jplhorizons ephemeris and orbital quantities, plus 'T-Tp'. """ import re from astropy.time import Time from astropy.table import Column, join, vstack from astroquery.jplhorizons import Horizons from .exceptions import EphemerisError # limit Horizons requests to 200 individual epochs (530 is # definitely too many) if not isinstance(epochs, dict): if len(epochs) > 200: eph = ephemeris(desg, epochs[:200], orbit=orbit) for i in range(200, len(epochs), 200): j = min(i + 200, len(epochs)) eph = vstack((eph, ephemeris(desg, epochs[i:j], orbit=orbit))) return eph opts = {} if re.match('^([CPID]/|[0-9]+P)', desg) is not None: id_type = 'designation' opts['closest_apparition'] = True opts['no_fragments'] = True else: id_type = 'smallbody' try: q = Horizons(id=desg, id_type=id_type, location='I41', epochs=epochs) eph = q.ephemerides(cache=False, **opts) except Exception as e: raise EphemerisError('{}: {}'.format(desg, str(e))) if len(eph) == 0: raise EphemerisError('{}'.format(desg)) # combine Tmag and Nmag into V if 'Tmag' in eph.colnames: V = eph['Tmag'] try: i = eph['Tmag'].mask V[i] = eph['Nmag'][i] except AttributeError as e: pass eph.add_column(V, name='V') V = eph['V'].data.astype(float) eph['V'] = Column(V, name='V') if orbit: q = Horizons(id=desg, id_type=id_type, location='0', epochs=epochs) orb = q.elements(cache=False, **opts) if len(orb) == 0: raise EphemerisError('{}'.format(desg)) Tp = Time(orb['Tp_jd'], format='jd', scale='tdb') T = Time(orb['datetime_jd'], format='jd', scale='utc') tmtp = (T - Tp).jd orb.add_column(Column(tmtp, name='T-Tp')) # remove repeated columns repeated = [ c for c in orb.colnames if (c in eph.colnames) and (c != 'datetime_jd') ] orb.remove_columns(repeated) # cheat to avoid float errors orb['datetime_jd'] = eph['datetime_jd'] eph = join(eph, orb) return eph
save_massive_states=True, epoch_scale='tdb', ), ) epoch = Time('2029-04-09T00:00:00', format='isot', scale='tdb') # 99942 Apophis # SPK ID = 2099942 # MINOR BODY ID = 2004 MN4 jpl_obj = Horizons( id='2004 MN4', location='500@10', epochs=epoch.jd, ) jpl_el = jpl_obj.elements() print(jpl_obj) print(jpl_el) for key in jpl_el.keys(): print(f'{key}:{jpl_el[key].data[0]}') orb = pyorb.Orbit( M0=pyorb.M_sol, direct_update=True, auto_update=True, degrees=True, a=jpl_el['a'].data[0] * pyorb.AU, e=jpl_el['e'].data[0], i=jpl_el['incl'].data[0], omega=jpl_el['w'].data[0], Omega=jpl_el['Omega'].data[0],
dic["z"].append(row["z"]) dic["vx"].append(row["vx"]) dic["vy"].append(row["vy"]) dic["vz"].append(row["vz"]) df = pd.read_csv("jfc_comets.csv") jfc_ids = np.random.choice(np.array(df.spkid, dtype=np.int), 100) ids_comets = [13699] + list(jfc_ids) print(ids_comets) for i in ids_comets: print(str(i)) try: obj = Horizons(id=str(i), location='@sun', epochs=2458133.33546, id_type='designation') row = obj.vectors()[0] el = obj.elements() a = el['a'] if a > 6: print("not a JFC") continue except ValueError as e: # print(e) continue dic["name"].append(row["targetname"]) dic["m"].append(1/(2e30)) dic["x"].append(row["x"]) dic["y"].append(row["y"]) dic["z"].append(row["z"]) dic["vx"].append(row["vx"]) dic["vy"].append(row["vy"]) dic["vz"].append(row["vz"])
def get_horizons_ephemerides(name, pov, epoch_start, epoch_stop, step_size, type_elements): # step: step size, [10m, 1d, 1y] if pov.lower() == 'sun': loc = '500@10' # position relative to the sun elif pov.lower() == 'goldstone': loc = '257' # from goldstone elif pov.lower() == 'maunakea': loc = '568' # maunakea else: print('Not Valid Location Point Of View') # Process to get homogeneity from main script full name '2012QD8' to a valid name for Horizon call '2012 QD8' if len( re.findall('([0-9])', name) ) <= 4: # 4 is the min numbers in every name, the date year of discovery r = re.compile("([0-9]+)([a-zA-Z]+)").match(name) k1 = r.group(1) # the date of the name k2 = r.group(2) # the code of the date valid_name = k1 + " " + k2 else: r = re.compile("([0-9]+)([a-zA-Z]+)([0-9]+)").match(name) k1 = r.group(1) # the date of the name k2 = r.group(2) # the code of the date k3 = r.group(3) # id after the letters valid_name = k1 + " " + k2 + k3 obj = Horizons(id=valid_name, location=loc, epochs={ 'start': epoch_start, 'stop': epoch_stop, 'step': step_size }) if type_elements.lower() == 'vectors': data = obj.vectors() # vectorial elements len_rows = len(data) len_cols = 6 # 3 positions 'x','y','z', and 3 velocities 'vx', 'vy', 'vz' idx_x = 5 # 'x' is at position 5 in the table (starting from 0) adata = np.zeros([len_rows, len_cols]) for row in range(len_rows): for col in range(6): idx_col_in_table = idx_x + col # because the 'x' start at 6th col, going up till the 12th that is 'vz' adata[row, col] = data[row][idx_col_in_table] elif type_elements.lower() == 'elements': # refsystem = 'J2000', # Element reference system for geometric and astrometric quantities # refplane = 'ecliptic' #ecliptic and mean equinox of reference epoch data = obj.elements(refsystem='J2000', refplane='ecliptic') len_rows = len(data) len_cols = 6 # (a e i OM om theta) adata = np.zeros([len_rows, len_cols]) for row in range(len_rows): adata[row, 0] = data[row][14] # 15th column of data -> semimajor axis adata[row, 1] = data[row][5] # 6th column of data -> eccentricity adata[row, 2] = data[row][7] # 8th column of data -> inclination adata[row, 3] = data[row][8] # 9th column of data -> RAAN, (OMEGA) adata[row, 4] = data[row][ 9] # 10th column of data -> argument of perigee, (omega) adata[row, 5] = data[row][ 13] # 14th column of data -> True anomaly, (theta) return adata
def get_horizons_ephemerides_elements(name, pov, epoch_start): # step: step size, [10m, 1d, 1y] if pov.lower() == 'sun': loc = '500@10' # position relative to the sun elif pov.lower() == 'goldstone': loc = '257' # from goldstone elif pov.lower() == 'maunakea': loc = '568' # maunakea else: print('Not Valid Location Point Of View') # Process to get homogeneity from main script full name '2012QD8' to a valid name for Horizon call '2012 QD8' if len( re.findall('([0-9])', name) ) <= 4: # 4 is the min numbers in every name, the date year of discovery r = re.compile("([0-9]+)([a-zA-Z]+)").match(name) k1 = r.group(1) # the date of the name k2 = r.group(2) # the code of the date valid_name = k1 + " " + k2 else: r = re.compile("([0-9]+)([a-zA-Z]+)([0-9]+)").match(name) k1 = r.group(1) # the date of the name k2 = r.group(2) # the code of the date k3 = r.group(3) # id after the letters valid_name = k1 + " " + k2 + k3 # always a day after the input, anyway you consider the moment of input, the first of the data output extracted epoch_start chunks = epoch_start.split('-') chunks2 = int(chunks[2]) + 1 # add 1 day list_string = [chunks[0], chunks[1], str(chunks2)] epoch_stop = '-'.join(list_string) step_size = '1d' obj = Horizons(id=valid_name, location=loc, epochs={ 'start': epoch_start, 'stop': epoch_stop, 'step': step_size }) # refsystem = 'J2000', # Element reference system for geometric and astrometric quantities # refplane = 'ecliptic' #ecliptic and mean equinox of reference epoch data = obj.elements(refsystem='J2000', refplane='ecliptic') len_cols = 7 # jd,ec,qr,tp,incl,OM,om adata = np.zeros([1, len_cols]) # always assign the first row of output data -> the first date required! #for row in range(len_rows): adata[0, 0] = data[0][5] # 6th column of data -> e, eccentricity (-) adata[0, 1] = data[0][6] # 7th column of data -> qr, periapsis distance (AU) adata[0, 2] = data[0][10] # 11th column of data -> tp, time of periapsis (JD) adata[0, 3] = data[0][7] # 8th column of data -> incl, inclination (deg) adata[0, 4] = data[0][ 8] # 10th column of data -> OM, longitude of Asc. Node (deg) adata[0, 5] = data[0][ 9] # 11th column of data -> om, argument of periapsis (deg) adata[0, 6] = data[0][ 1] # 2nd column of the data extracted -> jd of evaluation return adata
def from_horizons(cls, targetids, id_type='smallbody', epochs=None, center='500@10', **kwargs): """Load target orbital elements from `JPL Horizons <https://ssd.jpl.nasa.gov/horizons.cgi>`_ using `astroquery.jplhorizons.HorizonsClass.elements` Parameters ---------- targetids : str or iterable of str Target identifier, i.e., a number, name, designation, or JPL Horizons record number, for one or more targets. id_type : str, optional The nature of ``targetids`` provided; possible values are ``'smallbody'`` (asteroid or comet), ``'majorbody'`` (planet or satellite), ``'designation'`` (asteroid or comet designation), ``'name'`` (asteroid or comet name), ``'asteroid_name'``, ``'comet_name'``, ``'id'`` (Horizons id). Default: ``'smallbody'`` epochs : `~astropy.time.Time` object or iterable thereof, or dictionary, optional Epochs of elements to be queried; a list, tuple or `~numpy.ndarray` of `~astropy.time.Time` objects or Julian Dates as floats should be used for a number of discrete epochs; a dictionary including keywords ``start``, ``step``, and ``stop`` can be used to generate a range of epochs (see `~astroquery.jplhorizons.HorizonsClass.Horizons.elements` for details); if ``None`` is provided, current date and time are used. Default: ``None`` center : str, optional, default ``'500@10'`` (center of the Sun) Elements will be provided relative to this position. **kwargs : optional Arguments that will be provided to `astroquery.jplhorizons.HorizonsClass.elements`. Returns ------- `~Orbit` object Examples -------- >>> from sbpy.data import Orbit >>> from astropy.time import Time >>> epoch = Time('2018-05-14', scale='utc') >>> eph = Orbit.from_horizons('Ceres', epochs=epoch) """ # modify epoch input to make it work with astroquery.jplhorizons # maybe this stuff should really go into that module.... if epochs is None: epochs = [Time.now().jd] elif isinstance(epochs, Time): epochs = [Time(epochs).jd] elif isinstance(epochs, dict): for key, val in epochs.items(): if isinstance(val, Time): val.format = 'iso' val.out_subfmt = 'date_hm' epochs[key] = "'" + val.value + "'" else: epochs[key] = "'" + epochs[key] + "'" elif isinstance(epochs, (list, tuple, ndarray)): new_epochs = [None] * len(epochs) for i in range(len(epochs)): if isinstance(epochs[i], Time): new_epochs[i] = epochs[i].jd else: new_epochs[i] = epochs[i] epochs = new_epochs # if targetids is a list, run separate Horizons queries and append if not isinstance(targetids, (list, ndarray, tuple)): targetids = [targetids] # append elements table for each targetid all_elem = None for targetid in targetids: # load elements using astroquery.jplhorizons obj = Horizons(id=targetid, id_type=id_type, location=center, epochs=epochs) elem = obj.elements(**kwargs) # workaround for current version of astroquery to make # column units compatible with astropy.table.QTable # should really change '---' units to None in # astroquery.jplhorizons.__init__.py for column_name in elem.columns: if elem[column_name].unit == '---': elem[column_name].unit = None if all_elem is None: all_elem = elem else: all_elem = vstack([all_elem, elem]) # identify time scales returned by Horizons query timescales = ['TT'] * len(all_elem) all_elem.add_column(Column(timescales, name='timescale')) if bib.status() is None or bib.status(): bib.register('sbpy.data.Orbit.from_horizons', {'data service': '1996DPS....28.2504G'}) return cls.from_table(all_elem)
step = epochs[2] print(start) print(stop) print(step) obj = Horizons(id=planet[1], id_type=planet[2], location=planet[3], epochs={ 'start': start + '-01-01', 'stop': stop + '-01-01', 'step': step + 'd' }) try: elem = obj.elements() except ValueError: # no data available, just continue continue print(elem['targetname'][0]) elem['datetime_jd'] -= 2451544.5 # 1 jan 2000 00h00:00.00 elem['incl'].convert_unit_to('rad') elem['Omega'].convert_unit_to('rad') elem['w'].convert_unit_to('rad') elem['a'].convert_unit_to('m') elem['M'].convert_unit_to('rad') table = elem['datetime_jd', 'incl', 'Omega', 'w', 'e', 'a', 'M']