示例#1
0
def test_dummy(ccsds_format):

    with raises(TypeError):
        dumps(None, fmt=ccsds_format)

    with raises(CcsdsError):
        loads("dummy text")
示例#2
0
def test_dump_opm_man_continuous(orbit_continuous_man, datafile, ccsds_format, helper):
    ref = datafile("opm_continuous_man_tnw")
    txt = dumps(orbit_continuous_man, fmt=ccsds_format)

    helper.assert_string(ref, txt)

    ref = datafile("opm_continuous_man_qsw")

    for man in orbit_continuous_man.maneuvers:
        man.frame = "QSW"
        man._dv = np.array([man._dv[1], man._dv[0], man._dv[2]])

    txt = dumps(orbit_continuous_man, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#3
0
def test_dump_opm_interplanetary(jplfiles, orbit, ccsds_format, datafile,
                                 helper):
    create_frames("Mars")
    orbit.frame = "Mars"

    txt = dumps(orbit, fmt=ccsds_format)
    helper.assert_string(datafile("opm_interplanetary"), txt)
示例#4
0
def test_dump_oem_linear(ephem, ccsds_format):

    ephem.method = ephem.LINEAR
    txt = dumps(ephem, fmt=ccsds_format).splitlines()

    for line in txt:
        if "INTERPOLATION" in line:
            assert "LINEAR" in line
示例#5
0
def test_dump_omm_cov(orbit_cov, datafile, ccsds_format, helper):
    tle_cov = orbit_cov.copy(form="TLE")
    ref = datafile("omm_cov")
    txt = dumps(tle_cov, fmt=ccsds_format)

    helper.assert_string(ref, txt)

    tle_cov2 = tle_cov.copy()
    tle_cov2.cov.frame = "TNW"
    txt = dumps(tle_cov2, fmt=ccsds_format)
    helper.assert_string(datafile("omm_cov_tnw"), txt)

    tle_cov3 = tle_cov.copy()
    tle_cov3.cov.frame = "QSW"
    txt = dumps(tle_cov3, fmt=ccsds_format)

    helper.assert_string(datafile("omm_cov_qsw"), txt)
示例#6
0
def test_dump_opm(orbit, datafile, ccsds_format, helper, kep):

    kep = kep == "kep"

    ref = datafile("opm", kep)
    txt = dumps(orbit, fmt=ccsds_format, kep=kep)

    helper.assert_string(ref, txt)
示例#7
0
def test_dump_omm_user_defined(tle, ccsds_format, datafile, helper):

    subdict = tle._data["ccsds_user_defined"] = {}

    subdict["FOO"] = "foo enters"
    subdict["BAR"] = "a bar"
    txt = dumps(tle, fmt=ccsds_format)

    helper.assert_string(datafile("omm_user_defined"), txt)
示例#8
0
def test_dump_oem_interplanetary(jplfiles, ephem, ccsds_format, datafile,
                                 helper):

    ephem.frame = "MarsBarycenter"

    ref = datafile("oem_interplanetary")
    txt = dumps(ephem, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#9
0
def test_dump_opm_user_defined(orbit, ccsds_format, datafile, helper):

    subdict = orbit.complements["ccsds_user_defined"] = {}

    subdict["FOO"] = "foo enters"
    subdict["BAR"] = "a bar"
    txt = dumps(orbit, fmt=ccsds_format)

    helper.assert_string(datafile("opm_user_defined"), txt)
示例#10
0
def test_tle(tle, ccsds_format):
    # Check that a TLE and its OMM representation are the same

    txt = dumps(tle, fmt=ccsds_format)
    orb = loads(txt)
    new_tle = Tle.from_orbit(orb)
    assert str(tle.tle) == str(new_tle)

    assert all(tle == orb)
    date = Date(2020, 9, 30)
    assert all(tle.propagate(date) == orb.propagate(date))
示例#11
0
def test_dump_opm_cov(orbit_cov, datafile, ccsds_format, helper):

    ref = datafile("opm_cov")
    txt = dumps(orbit_cov, fmt=ccsds_format)

    helper.assert_string(ref, txt)

    # Conversion to TNW
    orbit_cov2 = orbit_cov.copy()
    orbit_cov2.cov.frame = "TNW"
    txt = dumps(orbit_cov2, fmt=ccsds_format)

    helper.assert_string(datafile("opm_cov_tnw"), txt)

    # Conversion to QSW
    orbit_cov3 = orbit_cov.copy()
    orbit_cov3.cov.frame = "QSW"
    txt = dumps(orbit_cov3, fmt=ccsds_format)

    helper.assert_string(datafile("opm_cov_qsw"), txt)
示例#12
0
def dumps(data, **kwargs):
    """Convert an Orbit or Ephem instance into a string formatted along the
    CCSDS standard

    This function is a wrapper of :py:func:`beyond.io.ccsds.dumps` and allows
    to integrate some space-command specific fields
    """

    if isinstance(data, Orbit):
        subdict = data.complements.setdefault("ccsds_user_defined", {})
        subdict["PROPAGATOR"] = data.propagator.__class__.__name__
        if data.propagator.__class__.__name__ == "KeplerNum":
            subdict["PROPAGATOR_STEP_SECONDS"] = "{:0.3f}".format(
                data.propagator.step.total_seconds())
            subdict["PROPAGATOR_METHOD"] = data.propagator.method

    return ccsds.dumps(data, **kwargs)
示例#13
0
def test_dump_omm_bluebook(ccsds_format, datafile, str_tle_bluebook):
    """Example from the CCSDS Blue Book (4-1 and 4-2)
    """

    tle = Tle(str_tle_bluebook)
    omm = tle.orbit()
    # omm.name = tle.name
    # omm.norad_id = tle.norad_id
    # omm.cospar_id = tle.cospar_id

    # assert tle.epoch == Date(2007, 5, 4, 10, 34, 41, 426400)

    omm = dumps(omm, fmt=ccsds_format).splitlines()
    ref_bluebook = datafile("omm_bluebook").splitlines()

    assert ref_bluebook[0] == omm[0]
    for i in range(4, len(ref_bluebook)):
        assert ref_bluebook[i] == omm[i]
示例#14
0
def space_ephem(*argv):  # pragma: no cover
    """Compute ephemeris from a given TLE

    Usage:
        space-ephem get <selector>...
        space-ephem insert (- | <file>)
        space-ephem compute (- | <selector>...) [options]
        space-ephem list <selector>... [options]

    Option
        get                   Retrieve an existing ephemeris from the database
        list                  List existing ephemerides
        compute               Compute ephemeris from a TLE
        insert                Insert a ephemeris into the database
        <selector>            Selector of the satellite
        -f, --frame <frame>   Frame in which to write the file to
        -d, --date <date>     Start date of the ephem [default: midnight]
                              (format %Y-%m-%dT%H:%M:%S)
        -r, --range <days>    Duration of extrapolation [default: 3d]
        -s, --step <step>     Step size of the ephemeris [default: 180s]
        -i, --interp <inter>  Interpolation method (linear, lagrange) [default: lagrange]
        --insert              Insert the computed ephemeris into the database
        --force               Force insertion
        -l, --last <last>     When listing print the last N ephems [default: 10]
    """

    from .utils import docopt
    from .sat import Sat

    args = docopt(space_ephem.__doc__, argv=argv)

    if args["compute"]:

        try:
            start = parse_date(args["--date"])
            stop = parse_timedelta(args["--range"])
            step = parse_timedelta(args["--step"])
            satlist = Sat.from_input(
                *args["<selector>"],
                text=sys.stdin.read() if args["-"] else "")
        except ValueError as e:
            log.error(e)
            sys.exit(1)

        ephems = []
        for sat in satlist:
            ephem = sat.orb.ephem(start=start, stop=stop, step=step)
            ephem.name = sat.name
            ephem.cospar_id = sat.cospar_id
            ephem.method = args["--interp"]
            if args["--frame"] is not None:
                ephem.frame = StationDb.get(args["--frame"])

            ephems.append(ephem)

        txt = ccsds.dumps(ephems,
                          originator=config.get("center",
                                                "name",
                                                fallback="N/A"))

        print(txt)
        print("")

    if args["insert"] or (args["compute"] and args["--insert"]):

        if args["--insert"]:
            pass
        elif args["-"] and not sys.stdin.isatty():
            txt = sys.stdin.read()
        else:
            txt = open(args["<file>"]).read()

        try:
            sats = Sat.from_input(text=txt, create=True)
        except ValueError as e:
            log.error(e)
            sys.exit(1)

        for sat in sats:
            db = EphemDb(sat)
            try:
                db.insert(sat.orb, args["--force"])
            except FileExistsError as e:
                continue
    elif args["list"]:

        max_idx = int(args["--last"])

        try:
            for sat in Sat.from_selector(*args["<selector>"], type="oem"):

                print(sat.name)
                print("idx  Start                Stop                 Steps")
                print("-" * 55)
                print(sat.req)

                for idx, ephem in enumerate(EphemDb(sat).list()):

                    if (sat.req.limit == "any" and idx == sat.req.offset
                            or ephem.start == sat.orb.start):
                        color = "* \033[32m"
                        endcolor = "\033[39m"
                    else:
                        color = "  "
                        endcolor = ""

                    if idx >= max_idx:
                        break

                    steps = set()
                    for orb_i, orb_j in zip(ephem[:-1], ephem[1:]):
                        steps.add(orb_j.date - orb_i.date)

                    if len(steps) == 1:
                        steps, = steps
                    else:
                        steps = "[{}, {}]".format(min(steps), max(steps))

                    print(
                        "{color}{idx:<2} {ephem.start:{fmt}}  {ephem.stop:{fmt}}  {steps}{endcolor}"
                        .format(
                            idx=idx,
                            ephem=ephem,
                            fmt="%Y-%m-%dT%H:%M:%S",
                            steps=steps,
                            color=color,
                            endcolor=endcolor,
                        ))
                print()
        except ValueError as e:
            log.error(e)
            sys.exit(1)

    elif args["get"]:
        ephems = []
        try:
            for sat in Sat.from_selector(*args["<selector>"], src="oem"):
                if not isinstance(sat.req.date, Date):
                    ephem = EphemDb(sat).get(offset=sat.req.offset)
                else:
                    ephem = EphemDb(sat).get_dated(date=sat.req.date,
                                                   limit=sat.req.limit)
                ephems.append(ephem)
        except ValueError as e:
            log.error(e)
            sys.exit(1)

        print(ccsds.dumps(ephems))
示例#15
0
def test_dump_omm(tle, datafile, ccsds_format, helper):
    ref = datafile("omm")
    txt = dumps(tle, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#16
0
def test_dump_oem_cov_tnw(ephem_cov, ccsds_format, datafile, helper):
    ephem_cov[0].cov.frame = "TNW"
    txt = dumps(ephem_cov, fmt=ccsds_format)
    helper.assert_string(datafile("oem_cov_tnw"), txt)
示例#17
0
def test_dump_oem_cov(ephem_cov, ccsds_format, datafile, helper):
    txt = dumps(ephem_cov, fmt=ccsds_format)
    helper.assert_string(datafile("oem_cov"), txt)
示例#18
0
def space_sat(*argv):
    """Get sat infos

    Usage:
      space-sat alias <alias> <selector> [--force]
      space-sat list-aliases
      space-sat orb <selector>
      space-sat sync
      space-sat infos <selector>

    Options:
      alias         Create an alias for quick access
      orb           Display the orbit corresponding to the selector
      list-aliases  List existing aliases
      sync          Update satellite database with existing TLEs
      infos         Display informations about a satellite
      <selector>    See below

    Satellite selectors
      ISS                : latest TLE of ISS
      norad=25544        : latest TLE of ISS selected by norad number
      cospar=2018-027A   : latest TLE of GSAT-6A
      ISS@oem            : latest OEM
      ISS@tle            : latest TLE
      ISS~               : before last TLE
      ISS~~              : 2nd before last TLE
      ISS@oem~25         : 25th before last OEM
      ISS@oem^2018-12-25 : first OEM after the date
      ISS@tle?2018-12-25 : first tle before the date
    """
    # TODO
    # ISS@opm            : latest OPM

    from .utils import docopt
    from .tle import space_tle
    from .ephem import space_ephem

    args = docopt(space_sat.__doc__, argv=argv)

    if args["alias"]:
        selector = args["<selector>"]
        name = args["<alias>"]

        try:
            sat = Sat.from_input(selector)
        except ValueError as e:
            log.error("Unknown satellite '{}'".format(selector))
            sys.exit(1)

        q = Alias.select().where(Alias.name == name)
        if q.exists():
            if args["--force"]:
                alias = q.get()
                alias.selector = selector
                alias.save()
                log.info("Alias '{}' ({}) created".format(name, selector))
            else:
                log.error("Alias '{}' already exists for '{}'".format(
                    name,
                    q.get().selector))
                sys.exit()
        else:
            Alias(selector=selector, name=name).save()
            log.info("Alias '{}' ({}) created".format(name, selector))

    elif args["list-aliases"]:
        for alias in Alias:
            print("{:20} {}".format(alias.name, alias.selector))

    elif args["sync"]:
        sync()

    elif args["orb"]:
        try:
            sat = list(Sat.from_selector(args["<selector>"]))[0]
        except ValueError as e:
            log.error(e)
            sys.exit(1)

        if isinstance(sat.orb, Ephem):
            print(ccsds.dumps(sat.orb))
        else:
            print("{0.name}\n{0}".format(sat.orb.tle))

    elif args["infos"]:
        try:
            sat, = Sat.from_input(args["<selector>"], orb=False)
            print("""name       {0.name}
cospar id  {0.cospar_id}
norad id   {0.norad_id}
folder     {0.folder}
    """.format(sat))
        except ValueError as e:
            log.error(e)
            sys.exit(1)
示例#19
0
def test_dump_opm_man_impulsive(orbit_man, datafile, ccsds_format, helper):

    ref = datafile("opm_impulsive_man")
    txt = dumps(orbit_man, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#20
0
def test_dump_oem(ephem, datafile, ccsds_format, helper):

    ref = datafile("oem")
    txt = dumps(ephem, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#21
0
def space_planet(*args):
    """Compute position of a planet of the solar system and its major moons

    Usage:
        space-planet
        space-planet fetch
        space-planet <planet>... [options]

    Options:
        fetch                Retrieve .bsp file
        <planet>             Names of the planet to compute the ephemeris of. If
                             absent, list all bodies available
        -f, --frame <frame>  Frame in which to display the ephemeris to
                             [default: EME2000]
        -d, --date <date>    Start date of the ephem (%Y-%m-%d) [default: midnight]
        -r, --range <days>   Duration of extrapolation [default: 3d]
        -s, --step <step>    Step size of the ephemeris. [default: 60m]
        -a, --analytical     Force analytical model instead of .bsp files

    Example:
        space-planet Mars  # Position of Mars in EME2000
        space-planet Moon -f Phobos  # Position of the moon as seen from Phobos

    This command relies on .bsp files, parsed by the incredible jplephem lib.
    Bsp file can be retrieved at

        https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/

    Files examples:

        de432s.bsp     Moon, Sun, Mercury, Venus and main bodies barycentre
        mar097.bsp     Mars, Phobos and Deimos
        jup310.bsp     Jupiter and its major moons
        sat360xl.bsp   Saturn and its major moons

    The 'beyond.env.jpl' config variable must be set to a list of bsp files
    paths. See beyond documentation about JPL files:

        http://beyond.readthedocs.io/en/latest/api/env.html#module-beyond.env.jpl

    If no .bsp file is provided, the command falls back to analytical methods
    for Moon and Sun. Other bodies are not provided.
    """

    import requests

    from logging import getLogger

    log = getLogger(__name__)

    args = docopt(space_planet.__doc__)

    if args["fetch"]:

        folder = ws.folder / "jpl"

        if not folder.exists():
            folder.mkdir()

        naif = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/"
        baseurl = {
            "de403_2000-2020.bsp":
            naif + "spk/planets/a_old_versions/",  # Data until 2020-01-01
            "de430.bsp": naif + "spk/planets/",
            "de432s.bsp": naif + "spk/planets/",
            "de435.bsp": naif + "spk/planets/",
            "jup310.bsp": naif + "spk/satellites/",
            "sat360xl.bsp": naif + "spk/satellites/",
            "mar097.bsp": naif + "spk/satellites/",
            "pck00010.tpc": naif + "pck/",
            "gm_de431.tpc": naif + "pck/",
        }

        success = []

        filelist = ws.config.get("beyond",
                                 "env",
                                 "jpl",
                                 fallback="de403_2000-2020.bsp")
        if not isinstance(filelist, list):
            filelist = [filelist]

        for filepath in filelist:

            filepath = Path(filepath)
            if not filepath.is_absolute():
                filepath = folder / filepath

            if not filepath.exists():

                url = baseurl.get(filepath.name, "") + str(filepath.name)
                log.info("Fetching {}".format(filepath.name))
                log.debug(url)

                try:
                    r = requests.get(url, stream=True)
                except requests.exceptions.ConnectionError as e:
                    log.error(e)
                else:
                    try:
                        r.raise_for_status()
                    except requests.exceptions.HTTPError as e:
                        log.error("{} {}".format(filepath.name, e))
                    else:
                        total = int(r.headers.get("content-length", 0))
                        size = 0
                        with filepath.open("bw") as fp:
                            for chunk in r.iter_content(chunk_size=1024):
                                fp.write(chunk)
                                if total:
                                    size += len(chunk)
                                    print(
                                        "\r> {:6.2f} %   {} / {}".format(
                                            100 * size / total,
                                            humanize(size),
                                            humanize(total),
                                        ),
                                        end="",
                                    )
                        if total:
                            print("\r", " " * 40, end="\r")
                        success.append(str(filepath.absolute()))
                        log.debug("Adding {} to the list of jpl files".format(
                            filepath.name))
            else:
                success.append(str(filepath.absolute()))
                log.info("File {} already downloaded".format(filepath.name))

        # Adding the file to the list and saving the new state of configuration
        if success:
            ws.config.set("beyond", "env", "jpl", success)

        ws.config.save()

    elif args["<planet>"]:

        try:
            date = parse_date(args["--date"], fmt="date")
            stop = parse_timedelta(args["--range"])
            step = parse_timedelta(args["--step"])
        except ValueError as e:
            print(e, file=sys.stderr)
            sys.exit(1)

        if not args["--analytical"]:
            # Create all frames from .bsp files, if they are available
            try:
                jpl.create_frames()
            except jpl.JplError:
                jpl_error = True
            else:
                jpl_error = False

        # Create all frames from stations database
        StationDb.list()

        try:
            frame = get_frame(args["--frame"])
        except UnknownFrameError as e:
            print(e, file=sys.stderr)
            sys.exit(1)

        # Computation
        ephems = []

        for body_name in args["<planet>"]:
            try:
                if args["--analytical"] or jpl_error:
                    body = solar.get_body(body_name).propagate(date)
                else:
                    body = jpl.get_orbit(body_name, date)
            except UnknownBodyError as e:
                print(e, file=sys.stderr)
                sys.exit(1)

            ephem = body.ephem(start=date, stop=stop, step=step)
            ephem.frame = frame
            ephem.name = body_name
            ephems.append(ephem)
        else:
            print(ccsds.dumps(ephems))
    else:
        print("List of all available bodies")
        try:
            jpl.create_frames()
            txt = recurse(jpl.get_frame("Earth").center.node, set())
        except jpl.JplError as e:
            print(" Sun")
            print(" Moon")
        else:
            print(txt)
示例#22
0
def test_dump(measureset, station, ccsds_format, datafile, helper):

    ref = datafile("tdm")
    txt = dumps(measureset, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#23
0
def test_dump_opm(orbit, datafile, ccsds_format, helper):

    ref = datafile("opm")
    txt = dumps(orbit, fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#24
0
def test_dump_double_oem(ephem, ephem2, datafile, ccsds_format, helper):

    ref = datafile("oem_double")
    txt = dumps([ephem, ephem2], fmt=ccsds_format)

    helper.assert_string(ref, txt)
示例#25
0
def test_dump_opm_man_continuous(orbit_continuous_man, datafile, ccsds_format,
                                 helper):
    ref = datafile("opm_impulsive_man")
    txt = dumps(orbit_continuous_man, fmt=ccsds_format)

    helper.assert_string(ref, txt, ignore="MAN_DURATION")