def search_sbdb(name): """Searchs JPL Small-Body DataBase to search for object information. As the name implies, it looks only for Small Bodies. Planets and satellites information are not retrieved by this function. Parameters: name (str): The name of the object for the search. It can be the used spkid or designation number. The name is case insensitive. Return: sbdb (dict): An OrderedDict with the object information Important note: The query is not an autocomplete search, so name='Charikl' will not find Chariklo. If more than 1 object is found, the user is asked to select the correct one (e.g: name='neowise') """ print('Obtaining data for {} from SBDB'.format(name)) sbdb = SBDB.query(name, full_precision=True, solution_epoch=True, validity=True, phys=True, discovery=True) if 'message' in sbdb: if sbdb['message'] == values.not_found_message: raise ValueError(values.not_found_message + " on SBDB") elif sbdb['message'] == values.many_objects_message: sbdb = select_body(sbdb) return sbdb
def queryJPL(designation): """Query JPL Horizons for information about object 'designation'. Parameters ---------- designation: str A name for the object that JPL Horizons will understand. Returns ------- pd.Series Series containing orbit and select physical information. """ sbdb = SBDB.query(designation, phys=True, full_precision=True) if 'orbit' not in sbdb: raise ValueError( 'Problem identifying orbit in returned information: %s', sbdb) orbval = sbdb['orbit']['elements'] phys = sbdb['phys_par'] if 'diameter' in phys: diam = phys['diameter'].to('km') else: diam = np.NaN if 'albedo' in phys: albedo = float(phys['albedo']) else: albedo = np.NaN if 'H' in phys: H = phys['H'] else: H = 999. if 'rot_per' in phys: rot = phys['rot_per'].to('hr') else: rot = np.NaN if 'fullname' in sbdb['object']: fullname = sbdb['object']['fullname'] else: fullname = sbdb['object']['des'] orbit = pd.Series( data={ 'des': sbdb['object']['des'], 'fullname': fullname, 'FORMAT': 'KEP', 'a': orbval['a'].to('AU'), 'q': orbval['q'].to('AU'), 'e': float(orbval['e']), 'inc': orbval['i'].to('deg'), 'Omega': orbval['om'].to('deg'), 'argPeri': orbval['w'].to('deg'), 'tPeri': orbval['tp'].to('d') - 2400000.5, # to MJD 'meanAnomaly': orbval['ma'].to('deg'), 'epoch': sbdb['orbit']['epoch'].to('d') - 2400000.5, # to MJD 'H': H, 'g': 0.15, 'diam': diam, 'albedo': albedo, 'rot': rot }) return orbit
def from_sbdb(cls, name, **kargs): """Return osculating `Orbit` by using `SBDB` from Astroquery. Parameters ---------- body_name: string Name of the body to make the request. Returns ------- ss: poliastro.twobody.orbit.Orbit Orbit corresponding to body_name Examples -------- >>> from poliastro.twobody.orbit import Orbit >>> apophis_orbit = Orbit.from_sbdb('apophis') """ obj = SBDB.query(name, full_precision=True, **kargs) if "count" in obj: # no error till now ---> more than one object has been found # contains all the name of the objects objects_name = obj["list"]["name"] objects_name_in_str = ( "" ) # used to store them in string form each in new line for i in objects_name: objects_name_in_str += i + "\n" raise ValueError( str(obj["count"]) + " different objects found: \n" + objects_name_in_str ) a = obj["orbit"]["elements"]["a"].to(u.AU) * u.AU ecc = float(obj["orbit"]["elements"]["e"]) * u.one inc = obj["orbit"]["elements"]["i"].to(u.deg) * u.deg raan = obj["orbit"]["elements"]["om"].to(u.deg) * u.deg argp = obj["orbit"]["elements"]["w"].to(u.deg) * u.deg # Since JPL provides Mean Anomaly (M) we need to make # the conversion to the true anomaly (\nu) nu = M_to_nu(obj["orbit"]["elements"]["ma"].to(u.deg) * u.deg, ecc) epoch = time.Time(obj["orbit"]["epoch"].to(u.d), format="jd") ss = cls.from_classical( Sun, a, ecc, inc, raan, argp, nu, epoch=epoch.tdb, plane=Planes.EARTH_ECLIPTIC, ) return ss
def getSBDBClass(obj_ids): data = {"targetname": [], "orbit_class": []} for obj_id in obj_ids: results = SBDB.query(obj_id) targetname = results["object"]["fullname"] orbit_class = results["object"]["orbit_class"]["name"] data["targetname"].append(targetname) data["orbit_class"].append(orbit_class) return pd.DataFrame(data)
def orbit_from_sbdb(name, **kwargs): obj = SBDB.query(name, full_precision=True, **kwargs) if "count" in obj: # No error till now ---> more than one object has been found # Contains all the name of the objects objects_name = obj["list"]["name"] objects_name_in_str = "" # Used to store them in string form each in new line for i in objects_name: objects_name_in_str += i + "\n" raise ValueError( str(obj["count"]) + " different objects found: \n" + objects_name_in_str) if "object" not in obj.keys(): raise ValueError(f"Object {name} not found") a = obj["orbit"]["elements"]["a"] ecc = float(obj["orbit"]["elements"]["e"]) * u.one inc = obj["orbit"]["elements"]["i"] raan = obj["orbit"]["elements"]["om"] argp = obj["orbit"]["elements"]["w"] # Since JPL provides Mean Anomaly (M) we need to make # the conversion to the true anomaly (nu) M = obj["orbit"]["elements"]["ma"].to(u.rad) # NOTE: It is unclear how this conversion should happen, # see https://ssd-api.jpl.nasa.gov/doc/sbdb.html if ecc < 1: M = (M + np.pi * u.rad) % (2 * np.pi * u.rad) - np.pi * u.rad nu = E_to_nu(M_to_E(M, ecc), ecc) elif ecc == 1: nu = D_to_nu(M_to_D(M)) else: nu = F_to_nu(M_to_F(M, ecc), ecc) epoch = Time(obj["orbit"]["epoch"].to(u.d), format="jd") return Orbit.from_classical( attractor=Sun, a=a, ecc=ecc, inc=inc, raan=raan, argp=argp, nu=nu, epoch=epoch.tdb, plane=Planes.EARTH_ECLIPTIC, )
def database_lookup(object_name): neo = SBDB.query(object_name) elements = neo['orbit']['elements'] #vecto = [elements['e'], # elements['a'], # elements['q'], # elements['i'], # elements['om'], # elements['w'], # elements['ma'], # elements['tp'], #elements['per'], # elements['n'], # elements['ad']] return (elements)
def from_sbdb(cls, name, **kargs): """Return osculating `Orbit` by using `SBDB` from Astroquery. Parameters ---------- body_name: string Name of the body to make the request. Returns ------- ss: poliastro.twobody.orbit.Orbit Orbit corresponding to body_name Examples -------- >>> from poliastro.twobody.orbit import Orbit >>> apophis_orbit = Orbit.from_sbdb('apophis') """ obj = SBDB.query(name, full_precision=True, **kargs) a = obj["orbit"]["elements"]["a"].to(u.AU) * u.AU ecc = float(obj["orbit"]["elements"]["e"]) * u.one inc = obj["orbit"]["elements"]["i"].to(u.deg) * u.deg raan = obj["orbit"]["elements"]["om"].to(u.deg) * u.deg argp = obj["orbit"]["elements"]["w"].to(u.deg) * u.deg # Since JPL provides Mean Anomaly (M) we need to make # the conversion to the true anomaly (\nu) nu = M_to_nu(obj["orbit"]["elements"]["ma"].to(u.deg) * u.deg, ecc) epoch = time.Time(obj["orbit"]["epoch"].to(u.d), format="jd") ss = cls.from_classical( Sun, a, ecc, inc, raan, argp, nu, epoch=epoch.tdb, plane=Planes.EARTH_ECLIPTIC, ) return ss
def sdss_colors(orbits, sdss_moc_filename='ADR4.dat'): sdss = read_sdss_moc(sdss_moc_filename) sdss = sdss.query('Name != "-"') jpl_des = np.zeros(len(sdss), dtype=object) for c, name in enumerate(sdss.Name.values): sbdb = SBDB.query(name.replace('_', ' ')) if 'object' in sbdb: jpl_des[c] = sbdb['object']['des'] sdss = sdss.assign(jpl_des=jpl_des) sdsscolors = {} bands = ('u', 'g', 'r', 'i', 'z', 'sdssa') errs = ('uerr', 'gerr', 'rerr', 'ierr', 'zerr', 'aerr') for band in bands: sdsscolors[band] = np.zeros(len(data)) - 999 for err in errs: sdsscolors[err] = np.zeros(len(data)) - 999 for c, des in enumerate(orbits.jpl_des.values): tmp = sdss.query('jpl_des == @des') if len(tmp) > 0: for band, err in zip(bands, errs): mags = sdss[des][band].values errors = sdss[des][err].values good = np.where((mags < 40) & (errors < 2)) if len(good[0]) > 0: mag = np.mean(mags[good]) errval = np.sqrt(np.sum(errors[good]**2)) sdsscolors[band][c] = mag sdsscolors[err][c] = errval colors = pd.DataFrame({ 'jpl_des': orbits.jpl_des.values, 'sdssa': sdsscolors['sdssa'], 'aerr': sdsscolors['aerr'], 'u': sdsscolors['u'], 'uerr': sdsscolors['uerr'], 'g': sdsscolors['g'], 'gerr': sdsscolors['gerr'], 'i': sdsscolors['i'], 'ierr': sdsscolors['ierr'], 'z': sdsscolors['z'], 'zerr': sdsscolors['zerr'] }) return colors
def from_sbdb(cls, targetids, references=False, notes=False): """Load physical properties from `JPL Small-Body Database (SBDB) <https://ssd.jpl.nasa.gov/sbdb.cgi>`_ using `~astroquery.jplsbdb` for one or more targets. Builds a `~Phys` object from the output of `'phys_par'` from SBDB. Units are applied, where available. Missing data are filled up as nan values. Note that SBDB only serves physical properties data for a limited number of objects. Parameters ---------- targetids : str, int or iterable thereof Target identifier(s) to be queried; use object numbers, names, or designations as unambiguous as possible. Returns ------- `~Phys` object Examples -------- >>> from sbpy.data import Phys >>> phys = Phys.from_sbdb(['Ceres', '12893', '3552']) # doctest: +REMOTE_DATA >>> print(phys['targetname', 'H', 'diameter']) # doctest: +SKIP targetname H diameter mag km -------------------------- ------------------ -------- 1 Ceres 3.34 939.4 12893 Mommert (1998 QS55) 13.9 5.214 3552 Don Quixote (1983 SA) 12.800000000000002 19.0 """ if not isinstance(targetids, (list, ndarray, tuple)): targetids = [targetids] alldata = [] columnnames = ['targetname'] columnunits = OrderedDict([('targetname', set())]) for targetid in targetids: sbdb = SBDB.query(str(targetid), phys=True) # assemble data from sbdb output data = OrderedDict([('targetname', sbdb['object']['fullname'])]) for key, val in sbdb['phys_par'].items(): if val is None or val == 'None': val = nan if '_note' in key: if notes: data[key] = val elif '_ref' in key: if references: data[key] = val else: try: if isnan(val): val = nan except TypeError: pass data[key] = val # add to columnnames if not yet there if key not in columnnames: columnnames.append(key) columnunits[key] = set() # identify units if isinstance(val, u.Quantity): columnunits[key].add(val.unit) elif isinstance(val, u.CompositeUnit): for unit in val.bases: columnunits[key].add(unit) alldata.append(data) # re-assemble data on a per-column basis coldata = [] for col in columnnames: data = [] for obj in alldata: try: data.append(obj[col]) except KeyError: data.append(nan) # identify common unit (or at least any unit) try: unit = list(columnunits[col])[0] # transform data to this unit newdata = [] for dat in data: if isinstance(dat, (u.Quantity, u.CompositeUnit)): try: newdata.append(dat.to(unit)) except u.UnitConversionError: # keep data untouched if conversion fails unit = 1 newdata = data break else: newdata.append(dat) except IndexError: # data has no unit assigned unit = 1 newdata = data # convert lists of strings to floats, where possible try: data = array(newdata).astype(float) except (ValueError, TypeError): data = newdata # apply unit, if available if unit != 1: coldata.append(data * unit) else: coldata.append(data) # assemble data as Phys object return cls.from_columns(coldata, names=columnnames)
def get_dict(name_list): """ # Return information for each bodies in name_list from JPL Small Body Database in form of dictionair # INPUT # name_list list [name1, name2, ..., nameN] # OUTPUT # dict_bodies dict with the following structure # str(name): "fullname" # "our_id" is the id inside the new dict, from 0 to N-1 where N is the name_list length # "neo_flag" # "orbit_class" # "pha_flag" # "object_kind" # "moid" # "orbita_elements" # "condition_code" # "rms" # "orbit_comment" # "magn_radius_flag" is "H" if the next parameter is the magnitude, is "D" if the next parameter is the diameter # "H" or "D" # "spectral_category_flag" T, S or 0 # "spectral_category" # "N_obs" Number of observations # "obs_span" Time between first and last observation # "impacts": str(impact id): 'width' # 'energy' # 'stretch' # 'ip' # 'dt' # 'date' # 'sigma_lov' # 'h' # 'mass' # 'v_inf' # 'sigma_imp' # 'method' # 'ts' # 'diam' # 'dist' # 'v_imp' # 'ps' """ our_id = 0 dict_bodies = {} for name in name_list: sbdb = SBDB.query(name, neo_only=True, full_precision=True, phys=True, virtual_impactor=True) if sbdb["object"]["kind"] != 'cn' or sbdb["object"]["kind"] != 'cu': asteroid = { "fullname": sbdb["object"]["fullname"], # TODO vogliamo fare un check? "our_id": our_id, "neo_flag": sbdb["object"]["neo"], "orbit_class": sbdb["object"]["orbit_class"]["code"], "pha_flag": sbdb["object"]["pha"], "object_kind": sbdb["object"] ["kind"], #an asteroid numbered au unbered asteroid (cn, cu for comet) "moid": sbdb["orbit"]["moid"], "orbital_elements": sbdb["orbit"]['elements'], "condition_code": sbdb["orbit"]["condition_code"], #OCC "rms": sbdb["orbit"]["rms"], "orbit_comment": sbdb["orbit"]["comment"], } try: asteroid["magn_radius_flag"] = 'H' asteroid["H"] = sbdb['phys_par']['H'] except: asteroid["magn_radius_flag"] = 'D' asteroid["D"] = sbdb['phys_par']['diameter'] asteroid["N_obs"] = sbdb['orbit']['n_obs_used'] asteroid["obs_span"] = sbdb['orbit']['data_arc'] asteroid["impacts"] = {} flag_bool = 1 if 'phys_par' in sbdb.keys(): spect_flag = 0 if 'spec_T' in sbdb['phys_par'].keys(): asteroid["spectral_category_flag"] = 'T' asteroid["spectral_category"] = sbdb['phys_par']['spec_T'] spect_flag = 1 if 'spec_B' in sbdb['phys_par'].keys(): asteroid["spectral_category_flag"] = 'B' asteroid["spectral_category"] = sbdb['phys_par']['spec_B'] spect_flag = 1 if spect_flag == 0: asteroid["spectral_category_flag"] = '0' else: asteroid["spectral_category"] = '0' if 'ip' in sbdb["vi_data"]: n_imp = len(sbdb["vi_data"]['ip']) for key in sbdb["vi_data"].keys(): if flag_bool == 1: for i in range(0, n_imp): asteroid["impacts"][str(i)] = {} flag_bool = 0 for i in range(0, n_imp): try: if isinstance(sbdb["vi_data"][key], str): asteroid["impacts"][str( i)][key] = sbdb["vi_data"][key] else: asteroid["impacts"][str( i)][key] = sbdb["vi_data"][key][i] except: print( name + " could raise error in importing virtual impact data" ) #this exception is raised if only one impact is present dict_bodies[name] = asteroid our_id = our_id + 1 flag_bool = 1 del asteroid return dict_bodies
def from_sbdb(cls, name, **kwargs): """Return osculating `Orbit` by using `SBDB` from Astroquery. Parameters ---------- name: str Name of the body to make the request. Returns ------- ss: poliastro.twobody.orbit.Orbit Orbit corresponding to body_name Examples -------- >>> from poliastro.twobody.orbit import Orbit >>> apophis_orbit = Orbit.from_sbdb('apophis') # doctest: +REMOTE_DATA """ from poliastro.bodies import Sun obj = SBDB.query(name, full_precision=True, **kwargs) if "count" in obj: # No error till now ---> more than one object has been found # Contains all the name of the objects objects_name = obj["list"]["name"] objects_name_in_str = ( "" # Used to store them in string form each in new line ) for i in objects_name: objects_name_in_str += i + "\n" raise ValueError( str(obj["count"]) + " different objects found: \n" + objects_name_in_str ) if "object" not in obj.keys(): raise ValueError(f"Object {name} not found") a = obj["orbit"]["elements"]["a"] ecc = float(obj["orbit"]["elements"]["e"]) * u.one inc = obj["orbit"]["elements"]["i"] raan = obj["orbit"]["elements"]["om"] argp = obj["orbit"]["elements"]["w"] # Since JPL provides Mean Anomaly (M) we need to make # the conversion to the true anomaly (nu) M = obj["orbit"]["elements"]["ma"].to(u.rad) # NOTE: It is unclear how this conversion should happen, # see https://ssd-api.jpl.nasa.gov/doc/sbdb.html if ecc < 1: M = (M + np.pi * u.rad) % (2 * np.pi * u.rad) - np.pi * u.rad nu = E_to_nu(M_to_E(M, ecc), ecc) elif ecc == 1: nu = D_to_nu(M_to_D(M)) else: nu = F_to_nu(M_to_F(M, ecc), ecc) epoch = time.Time(obj["orbit"]["epoch"].to(u.d), format="jd") ss = cls.from_classical( Sun, a, ecc, inc, raan, argp, nu, epoch=epoch.tdb, plane=Planes.EARTH_ECLIPTIC, ) return ss