Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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,
    )
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
    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