GithubHelp home page GithubHelp logo

brandon-rhodes / python-jplephem Goto Github PK

View Code? Open in Web Editor NEW
107.0 14.0 28.0 56.56 MB

Python version of NASA DE4xx ephemerides, the basis for the Astronomical Alamanac

License: MIT License

Python 99.33% Shell 0.33% Awk 0.34%

python-jplephem's Introduction

Welcome to the repository for the jplephem Python library!

The package is a Python implementation of the math that standard JPL ephemerides use to predict raw (x,y,z) planetary positions. It is one of the foundations of the Skyfield astronomy library for Python:

http://rhodesmill.org/skyfield/

But you can also use jplephem standalone to generate raw vectors. If that is your use case, then simply head over to its documentation and download link on the Python Package Index:

https://pypi.python.org/pypi/jplephem

If you want to install it with conda, there is a recipe at:

https://github.com/conda-forge/jplephem-feedstock

This repository is where jplephem is maintained. You will find its source code beneath the jplephem directory that sits alongside the setup.py file. You can run its tests with:

wget https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/a_old_versions/de405.bsp
wget https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/a_old_versions/de421.bsp
pip install de421
python -m unittest discover jplephem

Enjoy!

python-jplephem's People

Contributors

astrojuanlu avatar avalentino avatar brandon-rhodes avatar deuchnord avatar helgee avatar jayvdb avatar jcaesar avatar jdavies-st avatar mhvk avatar nbelakovski avatar toddrme2178 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-jplephem's Issues

Can this read little-endian binary JPL files?

Hello. I already have the little-endian binary JPL files downloaded from ftp://ssd.jpl.nasa.gov/pub/eph/planets/Linux/de431/. But the code/doc seems only to talk about BSP files.

Does this mean I have to download the files from under ftp://ssd.jpl.nasa.gov/pub/eph/planets/bsp/?

Since the files aren't small I'm wary of downloading and using up my bandwidth unnecessarily.

Further some of those files have t s etc appended to the DE version number and I'm not sure what to use…

Please help! Thank you!

Information on coordinate systems needed

This is not a real issue but more a question:
I want to get the position and velocities of planets and moons relative to solar system barycenter. The pypi documentation gives some very good hints. However, it seems that I have a misunderstanding of the coordinate system: As the orbits of e.g. mars and earth are more or less in a plane, I would expect to have at least one component of (x,y,z) magnitudes smaller than the others. However, the result proves me wrong:

>>> position = kernel[0,4].compute(2457061.5)
>>> print(position)
[2.057e+08 4.251e+07 1.394e+07]

Any hint for documentation of the coordinate system would help. I could not get my head around SPK Required Read.

In addition, a hint how to chain kernels and calculate the velocity of any object with respect to the solar system barycenter would be great. E.g. Solar System Barycenter (0) -> Earth Barycenter (3) -> Moon (301)

Sorry for posting it as issue, but I don't know where to raise this question.

Many time intervals for segments with same values

Hello

There are some BSP files I work that have many segments with same values, each with different time intervals.

For example:

<-->**k=SPK.open("chariklo_jpl20.bsp")**

<-->**print(k)**
....
2487340.50..2487468.50  Sun (10) -> Unknown Target (2010199)
2487468.50..2487596.50  Sun (10) -> Unknown Target (2010199)
2487596.50..2487724.50  Sun (10) -> Unknown Target (2010199)
2487724.50..2487852.50  Sun (10) -> Unknown Target (2010199)
2487852.50..2487980.50  Sun (10) -> Unknown Target (2010199)
2487980.50..2488108.50  Sun (10) -> Unknown Target (2010199)
2488108.50..2488236.50  Sun (10) -> Unknown Target (2010199)
2488236.50..2488364.50  Sun (10) -> Unknown Target (2010199)
2488364.50..2488428.50  Sun (10) -> Unknown Target (2010199)
2488402.50..2488434.50  Sun (10) -> Unknown Target (2010199)

<--->  **k[10,2010199].compute(2457023.5)**

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)
<ipython-input-46-333d3990b7b5> in <module>()
----> 1 k[10,2010199].compute(2457023.5)

/home/altairjunior/anaconda/lib/python2.7/site-packages/jplephem/spk.pyc in compute(self, tdb, tdb2)
    104     def compute(self, tdb, tdb2=0.0):
    105         """Compute the component values for the time `tdb` plus `tdb2`."""
--> 106         for position in self.generate(tdb, tdb2):
    107             return position
    108 

/home/altairjunior/anaconda/lib/python2.7/site-packages/jplephem/spk.pyc in generate(self, tdb, tdb2)
    164             final_epoch = initial_epoch + interval_length * n
    165             raise ValueError('segment only covers dates %.1f through %.1f'
--> 166                             % (initial_epoch, final_epoch))
    167 
    168         omegas = (index == n)

ValueError: segment only covers dates 2488402.5 through 2488434.5

So, it only gets the last segment and does not compute for instant in the middle

Is there any way to avoid this?

How to make a PR against pypi documentation?

I'd like to make a note in the pypi documentation that the timestamp being used is the julian date. This wasn't obvious to me as I was diving into this and it's not immediately obvious from the (copious) SPICE documentation that this is the case. I don't see that documentation in this repo, is it updated manually or is there another repo where I could submit an edit?

Ephemeris coordinates do not match JPL horizons

I've been doing some comparisons between the output of jplephem and that from the JPL horizons web interface, and there seem to be some large discrepancies. It may be that I'm misunderstanding what the output of jplephem produces, but I wanted to run my test by you just to check. I'm using the latest version of jplephem from PyPI (and have also testing using the interface through astropy v2.0.3).

If I run the following:

from astropy.utils.data import download_file
from jplephem.spk import SPK

# get the DE430 ephemeris
kernel = SPK.open(download_file('https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de430.bsp'))

# get Mars position wrt the SSB at JD 2457061.5
position = kernel[0,4].compute(2457061.5)
print(position)
[2.05700211e+08 4.25141646e+07 1.39379183e+07]

Now, if I try and get the same thing from JPL Horizons, with settings:

Ephemeris Type [change] : VECTORS
Target Body [change] : Mars [499]
Coordinate Origin [change] : Solar System Barycenter (SSB) [500@0]
Time Span [change] : discrete time(s)=2457061.5
Table Settings [change] : quantities code=2; output units=KM-D
Display/Output [change] : default (formatted HTML)

I get an output of:

*******************************************************************************
Ephemeris / WWW_USER Fri Feb  2 12:14:04 2018 Pasadena, USA      / Horizons    
*******************************************************************************
Target body name: Mars (499)                      {source: mar097}
Center body name: Solar System Barycenter (0)     {source: DE431mx}
Center-site name: BODY CENTER
*******************************************************************************
Start time      : A.D. 2015-Feb-08 00:00:00.0000 TDB
Stop  time      : A.D. 2015-Feb-09 00:00:00.0000 TDB
Step-size       : 0 steps
*******************************************************************************
Center geodetic : 0.00000000,0.00000000,0.0000000 {E-lon(deg),Lat(deg),Alt(km)}
Center cylindric: 0.00000000,0.00000000,0.0000000 {E-lon(deg),Dxy(km),Dz(km)}
Center radii    : (undefined)                                                  
Output units    : KM-D                                                         
Output type     : GEOMETRIC cartesian states
Output format   : 2 (position and velocity)
Reference frame : ICRF/J2000.0                                                 
Coordinate systm: Ecliptic and Mean Equinox of Reference Epoch                 
*******************************************************************************
JDTDB
   X     Y     Z
   VX    VY    VZ
*******************************************************************************
$$SOE
2457061.500000000 = A.D. 2015-Feb-08 00:00:00.0000 TDB 
 X = 2.057002106297807E+08 Y = 4.455016893516217E+07 Z =-4.123373332901161E+06
 VX=-3.638960654558704E+05 VY= 2.225391521054880E+06 VZ= 5.554317182156630E+04
$$EOE
*******************************************************************************
Coordinate system description:

  Ecliptic and Mean Equinox of Reference Epoch

    Reference epoch: J2000.0
    XY-plane: plane of the Earth's orbit at the reference epoch
              Note: obliquity of 84381.448 arcseconds wrt ICRF equator (IAU76)
    X-axis  : out along ascending node of instantaneous plane of the Earth's
              orbit and the Earth's mean equator at the reference epoch
    Z-axis  : perpendicular to the xy-plane in the directional (+ or -) sense
              of Earth's north pole at the reference epoch.

  Symbol meaning [1 day=86400.0 s]:

    JDTDB    Julian Day Number, Barycentric Dynamical Time
      X      X-component of position vector (km)                               
      Y      Y-component of position vector (km)                               
      Z      Z-component of position vector (km)                               
      VX     X-component of velocity vector (km/day)                           
      VY     Y-component of velocity vector (km/day)                           
      VZ     Z-component of velocity vector (km/day)                           

Geometric states/elements have no aberrations applied.

 Computations by ...
     Solar System Dynamics Group, Horizons On-Line Ephemeris System
     4800 Oak Grove Drive, Jet Propulsion Laboratory
     Pasadena, CA  91109   USA
     Information: http://ssd.jpl.nasa.gov/
     Connect    : telnet://ssd.jpl.nasa.gov:6775  (via browser)
                  http://ssd.jpl.nasa.gov/?horizons
                  telnet ssd.jpl.nasa.gov 6775    (via command-line)
     Author     : [email protected]
*******************************************************************************

So, if I do the difference between the two outputs I get

# JPL Horizons output
hori = [2.057002106297807E+08, 4.455016893516217E+07, -4.123373332901161E+06]

np.array(position)-np.array(hori)
[ 4.41484749e-02, -2.03600436e+06,  1.80612916e+07]

i.e., the x position seems to be accurate to ~44m, but the y and z values are completely wrong.

Is there some coordinate system difference that I'm not taking into account, i.e. with the JPL ephemeris using Coordinate systm: Ecliptic and Mean Equinox of Reference Epoch, or is there something else wrong with what I have done. I see that the JPL Horizons system is using the DE431 ephemeris, but according to this note planet positions from DE430 and DE431 should agree to within 0.001 km. I find similar discrepancies for tests with other planets and time values.

Hopefully this is just my misunderstanding of the output the compute() method or coordinate system.

jplephem should cleanup resources better

Use case

I have a file (ast343de430.bsp) containing about 300 bodies. I want to plot the positions of all the bodies at one given instant of time.

Problem

When I use the following code

import numpy as np
from jplephem.spk import SPK 
kernel = SPK.open('ast343de430.bsp')
pos = np.array([kernel[p].compute(2457061.5) for p in kernel.pairs.keys()])

I get: OSError: [Errno 24] Too many open files

Expected behavior

Each call to kernel[p].compute(2457061.5) should clean up such that we don't run into this issue.

Kudos

BTW, library writers often just get gripes from users, so I'd like to point out here that I really like jplephem and it is my go to Python solution for all things SPK related. Thank you for all the effort you have put into it!

The conda-forge package for jplephem is out of date (v2.9 instead of v2.12)

Not sure if this is the correct reporting forum for this...

I'm need to use skyfield on multiple user-level windows systems and anaconda env management is the simplest way to organize this. Want to be able to tell the end users, "Download anaconda and then create an env using this file". Currently skyfield reports an error due to an out of date jplephem.

The workaround is to force install jplephem with pip since the pypi repo is up to date, but this is not viable for my end users.

Unable to run jpltest

I got this error trying to run jpltest both in version v1.0 and latest from master:

python -m jplephem.jpltest
de421 AU = 149597870.7 km
Traceback (most recent call last):
  File "/usr/lib/python3.3/runpy.py", line 160, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python3.3/runpy.py", line 73, in _run_code
    exec(code, run_globals)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 102, in <module>
    test_all()
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 97, in test_all
    testpo(ephemeris, fname)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 29, in testpo
    tpos = _position(ephemeris, jed, target)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 67, in _position
    return c('jupiter', jed)
TypeError: compute() got an unexpected keyword argument 'differentiate'

FWIW, I edited line 90 in jpltest.py to be

for number in 421,:

because I had downloaded only one ephemeries. But I don't think it matters, or does it?

data type 1 SPK kernel

I have downloaded an SPK kernel of data type 1 form JPL horizons http://ssd.jpl.nasa.gov/x/spk.html in binary and ascii format. The kernel can be loaded using jplephem.spk.SPK but I get an error when I compute the position of an object.

In [22]: kernel[10,1000012].compute(2457400)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/mdevalbo/.local/lib/python3.5/site-packages/jplephem/spk.py in generate(self, tdb, tdb2)
    151         try:
--> 152             initial_epoch, interval_length, coefficients = self._data
    153         except AttributeError:

AttributeError: 'Segment' object has no attribute '_data'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-22-5dbf5fd43a50> in <module>()
----> 1 kernel[10,1000012].compute(2457400)

/home/mdevalbo/.local/lib/python3.5/site-packages/jplephem/spk.py in compute(self, tdb, tdb2)
    104     def compute(self, tdb, tdb2=0.0):
    105         """Compute the component values for the time `tdb` plus `tdb2`."""
--> 106         for position in self.generate(tdb, tdb2):
    107             return position
    108 

/home/mdevalbo/.local/lib/python3.5/site-packages/jplephem/spk.py in generate(self, tdb, tdb2)
    152             initial_epoch, interval_length, coefficients = self._data
    153         except AttributeError:
--> 154             self._data = self._load()
    155             initial_epoch, interval_length, coefficients = self._data
    156 

/home/mdevalbo/.local/lib/python3.5/site-packages/jplephem/spk.py in _load(self)
    120             component_count = 6
    121         else:
--> 122             raise ValueError('only SPK data types 2 and 3 are supported')
    123 
    124         init, intlen, rsize, n = self.daf.map_array(self.end_i - 3, self.end_i)

ValueError: only SPK data types 2 and 3 are supported

Is there any way to get an SPK kernel from Horizons that is supported by jplephem?

Unable to excerpt kernel with many segments

I found this problem while trying to excerpt kernels over a time period that overlaps more than one segment for the same body, see #20, but I suspect thath the problem is more general.

Let me show the bug with an example using de441.bsp from https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp.

Structure of `de441.bsp`
$ python -m jplephem spk de441.bsp 
File type DAF/SPK and format LTL-IEEE with 28 segments:
-3100015.50..2440432.50  Type 2  Venus Barycenter (2) -> Venus (299)
-3100015.50..2440432.50  Type 2  Mercury Barycenter (1) -> Mercury (199)
-3100015.50..2440432.50  Type 2  Earth Barycenter (3) -> Earth (399)
-3100015.50..2440432.50  Type 2  Earth Barycenter (3) -> Moon (301)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Sun (10)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Pluto Barycenter (9)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Neptune Barycenter (8)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Uranus Barycenter (7)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Saturn Barycenter (6)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Jupiter Barycenter (5)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Mars Barycenter (4)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Venus Barycenter (2)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Mercury Barycenter (1)
2440432.50..8000016.50  Type 2  Venus Barycenter (2) -> Venus (299)
2440432.50..8000016.50  Type 2  Mercury Barycenter (1) -> Mercury (199)
2440432.50..8000016.50  Type 2  Earth Barycenter (3) -> Earth (399)
2440432.50..8000016.50  Type 2  Earth Barycenter (3) -> Moon (301)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Sun (10)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Pluto Barycenter (9)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Neptune Barycenter (8)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Uranus Barycenter (7)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Saturn Barycenter (6)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Jupiter Barycenter (5)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Mars Barycenter (4)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Venus Barycenter (2)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Mercury Barycenter (1)
$ python -m jplephem daf de441.bsp 
 1 DE-0441LE-0441 -479654827200.0 -960120000.0 299 2 1 2 8065 8076
 2 DE-0441LE-0441 -479654827200.0 -960120000.0 199 1 1 2 8077 8088
 3 DE-0441LE-0441 -479654827200.0 -960120000.0 399 3 1 2 8089 56797684
 4 DE-0441LE-0441 -479654827200.0 -960120000.0 301 3 1 2 56797685 113587280
 5 DE-0441LE-0441 -479654827200.0 -960120000.0 10 0 1 2 113587281 125707014
 6 DE-0441LE-0441 -479654827200.0 -960120000.0 9 0 1 2 125707015 129169798
 7 DE-0441LE-0441 -479654827200.0 -960120000.0 8 0 1 2 129169799 132632582
 8 DE-0441LE-0441 -479654827200.0 -960120000.0 7 0 1 2 132632583 136095366
 9 DE-0441LE-0441 -479654827200.0 -960120000.0 6 0 1 2 136095367 140077567
10 DE-0441LE-0441 -479654827200.0 -960120000.0 5 0 1 2 140077568 144579185
11 DE-0441LE-0441 -479654827200.0 -960120000.0 4 0 1 2 144579186 150639054
12 DE-0441LE-0441 -479654827200.0 -960120000.0 3 0 1 2 150639055 164836456
13 DE-0441LE-0441 -479654827200.0 -960120000.0 2 0 1 2 164836457 175917356
14 DE-0441LE-0441 -479654827200.0 -960120000.0 1 0 1 2 175917357 206389824
15 DE-0441LE-0441 -960120000.0 479387937600.0 299 2 1 2 206389825 206389836
16 DE-0441LE-0441 -960120000.0 479387937600.0 199 1 1 2 206389837 206389848
17 DE-0441LE-0441 -960120000.0 479387937600.0 399 3 1 2 206389849 263375588
18 DE-0441LE-0441 -960120000.0 479387937600.0 301 3 1 2 263375589 320361328
19 DE-0441LE-0441 -960120000.0 479387937600.0 10 0 1 2 320361329 332522922
20 DE-0441LE-0441 -960120000.0 479387937600.0 9 0 1 2 332522923 335997666
21 DE-0441LE-0441 -960120000.0 479387937600.0 8 0 1 2 335997667 339472410
22 DE-0441LE-0441 -960120000.0 479387937600.0 7 0 1 2 339472411 342947154
23 DE-0441LE-0441 -960120000.0 479387937600.0 6 0 1 2 342947155 346943109
24 DE-0441LE-0441 -960120000.0 479387937600.0 5 0 1 2 346943110 351460275
25 DE-0441LE-0441 -960120000.0 479387937600.0 4 0 1 2 351460276 357541074
26 DE-0441LE-0441 -960120000.0 479387937600.0 3 0 1 2 357541377 371787814
27 DE-0441LE-0441 -960120000.0 479387937600.0 2 0 1 2 371787815 382906986
28 DE-0441LE-0441 -960120000.0 479387937600.0 1 0 1 2 382906987 413484702

In this file 1969-07-30T00:00 is the cutoff between the two segments. If I ask for the 1969/7/29 1969/7/31 time span I get

$ python -m jplephem excerpt 1969/7/29 1969/7/31 de441.bsp de441_partial.bsp 
Date 1969/7/29  = JD 2440432
Date 1969/7/31  = JD 2440434

'de441_partial.bsp' written successfully with the following contents

File type DAF/SPK and format LTL-IEEE with 3 segments:
2440432.50..2440448.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)
2440432.50..2440448.50  Type 2  Solar System Barycenter (0) -> Venus Barycenter (2)
2440432.50..2440440.50  Type 2  Solar System Barycenter (0) -> Mercury Barycenter (1)
$ python -m jplephem daf de441_partial.bsp 
 1 XE-0441LE-0441 -960120000.0 -958737600.0 3 0 1 2 9217 9261
 2 XE-0441LE-0441 -960120000.0 -958737600.0 2 0 1 2 9262 9297
 3 XE-0441LE-0441 -960120000.0 -959428800.0 1 0 1 2 9298 9345

28 segments are expected, but only the last 3 segments are present in the summary.

My conjecture (I had no time to do a complete debugging) is that the summary gets overwritten in DAF.add_array. See the following examples.

Excerpetd file with 24 segments is OK:

 $ python -m jplephem excerpt --target 299,199,399,301,10,9,8,7,6,5,4,3 1969/7/29 1969/7/31 de441.bsp de441_partial.bsp 
Date 1969/7/29  = JD 2440432
Date 1969/7/31  = JD 2440434

'de441_partial.bsp' written successfully with the following contents

File type DAF/SPK and format LTL-IEEE with 24 segments:
-3100015.50..2440432.50  Type 2  Venus Barycenter (2) -> Venus (299)
-3100015.50..2440432.50  Type 2  Mercury Barycenter (1) -> Mercury (199)
2440428.50..2440432.50  Type 2  Earth Barycenter (3) -> Earth (399)
2440428.50..2440432.50  Type 2  Earth Barycenter (3) -> Moon (301)
2440416.50..2440432.50  Type 2  Solar System Barycenter (0) -> Sun (10)
2440400.50..2440432.50  Type 2  Solar System Barycenter (0) -> Pluto Barycenter (9)
2440400.50..2440432.50  Type 2  Solar System Barycenter (0) -> Neptune Barycenter (8)
2440400.50..2440432.50  Type 2  Solar System Barycenter (0) -> Uranus Barycenter (7)
2440400.50..2440432.50  Type 2  Solar System Barycenter (0) -> Saturn Barycenter (6)
2440400.50..2440432.50  Type 2  Solar System Barycenter (0) -> Jupiter Barycenter (5)
2440400.50..2440432.50  Type 2  Solar System Barycenter (0) -> Mars Barycenter (4)
2440416.50..2440432.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)
2440400.50..8000016.50  Type 2  Venus Barycenter (2) -> Venus (299)
2440400.50..8000016.50  Type 2  Mercury Barycenter (1) -> Mercury (199)
2440432.50..2440436.50  Type 2  Earth Barycenter (3) -> Earth (399)
2440432.50..2440436.50  Type 2  Earth Barycenter (3) -> Moon (301)
2440432.50..2440448.50  Type 2  Solar System Barycenter (0) -> Sun (10)
2440432.50..2440464.50  Type 2  Solar System Barycenter (0) -> Pluto Barycenter (9)
2440432.50..2440464.50  Type 2  Solar System Barycenter (0) -> Neptune Barycenter (8)
2440432.50..2440464.50  Type 2  Solar System Barycenter (0) -> Uranus Barycenter (7)
2440432.50..2440464.50  Type 2  Solar System Barycenter (0) -> Saturn Barycenter (6)
2440432.50..2440464.50  Type 2  Solar System Barycenter (0) -> Jupiter Barycenter (5)
2440432.50..2440464.50  Type 2  Solar System Barycenter (0) -> Mars Barycenter (4)
2440432.50..2440448.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)

Excerpted file with 26 expected segments is truncated:

$ python -m jplephem excerpt --target 299,199,399,301,10,9,8,7,6,5,4,3,2 1969/7/29 1969/7/31 de441.bsp de441_partial.bsp 
Date 1969/7/29  = JD 2440432
Date 1969/7/31  = JD 2440434

'de441_partial.bsp' written successfully with the following contents

File type DAF/SPK and format LTL-IEEE with 1 segments:
2440432.50..2440448.50  Type 2  Solar System Barycenter (0) -> Venus Barycenter (2)

Note: all examples run against commit 785c155 on MacOS.

Segments with same keys

Hi, It's me again :)

I sucessful loaded the file de441.bsp

File type DAF/SPK and format LTL-IEEE with 28 segments:
-3100015.50..2440432.50  Type 2  Venus Barycenter (2) -> Venus (299)
-3100015.50..2440432.50  Type 2  Mercury Barycenter (1) -> Mercury (199)
-3100015.50..2440432.50  Type 2  Earth Barycenter (3) -> Earth (399)
-3100015.50..2440432.50  Type 2  Earth Barycenter (3) -> Moon (301)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Sun (10)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Pluto Barycenter (9)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Neptune Barycenter (8)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Uranus Barycenter (7)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Saturn Barycenter (6)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Jupiter Barycenter (5)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Mars Barycenter (4)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Venus Barycenter (2)
-3100015.50..2440432.50  Type 2  Solar System Barycenter (0) -> Mercury Barycenter (1)
2440432.50..8000016.50  Type 2  Venus Barycenter (2) -> Venus (299)
2440432.50..8000016.50  Type 2  Mercury Barycenter (1) -> Mercury (199)
2440432.50..8000016.50  Type 2  Earth Barycenter (3) -> Earth (399)
2440432.50..8000016.50  Type 2  Earth Barycenter (3) -> Moon (301)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Sun (10)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Pluto Barycenter (9)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Neptune Barycenter (8)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Uranus Barycenter (7)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Saturn Barycenter (6)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Jupiter Barycenter (5)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Mars Barycenter (4)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Earth Barycenter (3)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Venus Barycenter (2)
2440432.50..8000016.50  Type 2  Solar System Barycenter (0) -> Mercury Barycenter (1)

Note that the kernel have duplicated keys!
When I try to select from kernel the Earth Barycenter with pair (0,3), it give me the last one. I know that it is a normal behavior of Python.
When a dictionary have duplicate keys, it choose the last one

>> d = {"a": [1, 2], "b": [3, 4], "a": [10,20]}
>> d["a"]
[10, 20]

The problem is when I using astropy with ephemeris = de441.bsp, it use your package to get coordinates, and it fails to select the first one.

from astropy.time import Time
from astropy import coordinates as coord

coord.solar_system_ephemeris.set('bsp/de441.bsp')

coord.get_moon(Time("1950-03-26 17:00:00", format="iso")) # it fails

The problem occur in line 278, of file solar_system.py inside coordinates subpackage

     for pair in kernel_spec:
            spk = kernel[pair]
...

Is this problem of the file de441.bsp ?

obs.: if you prefer, I can open this issue on astropy repo

Retrieve input parameters for ephemeris

If I understand correctly, SPICE kernels don't have the set of input parameters used to integrate the model, which are however available from the ASCII files (see for example de421):

ftp://ssd.jpl.nasa.gov/pub/eph/planets/ascii/de421/header.421

It is the case that each ephemeris has its own set of mass parameters for the planetary bodies, so I think it makes sense to have the corresponding constants when loading an ephemeris.

Do you think it is worth it to provide some kind of optional parameter so the user can provide also the corresponding header file? Also, are you aware of already written functions to deal with that kind of format?

Velocities units

Why does compute_and_differentiate return velocities as km/day instead of more common km/sec ?

Comparison with JPL Horizons

In comparison with the data from JPL Horizons it gives some error:

JPL: [-1.10659532e+08  9.70047434e+07 -2.39525979e+04]
JL:   [-1.10369890e+08  8.93069592e+07  3.86931886e+07]

Hovewer in the documentation it's stated that The package's test suite uses test files provided by JPL to confirm that the results are correct.

The code:

using JPLEphemeris

spk = SPK("de430.bsp")
jd = parse(Float64,"2457388.33750")
st = state(spk, 0, 3, [jd])

Position difference between spiceypy and jplephem (order of 1e-5 km); velocity OK

Foremost, thanks for coding and maintaining jplephem. It's really an excellent library. In fact, I've implemented my own ephemeris reader using some of your work.

As demonstrated by the following example code, there is a position difference between spiceypy and jplephem on the order of 1e-5km. The velocity difference is on the order of 1e-12 km/s. The velocity error is small enough to not impact my work, but the position error is a bit more concerning. In general however, I would expect the difference to be machine precision (1e-16 on my computer).

I dove into the SPK Required Reading document to identify any differences in the way the position is computed, but that effort turned out fruitless.

Do you have any hint as to what could cause that difference? I'd be happy to dive into it myself.

Example

Code

from jplephem.spk import SPK
import spiceypy as sp

# These numbers are computed using hifitime https://github.com/ChristopherRabotin/hifitime/
# This date time corresponds to 07 February 2002 at midnight TAI.
jde_et_days = 2452312.5007428810931742
jde_et_secs = 66312064.18493939

# SPICE
sp.furnsh('de438s.bsp')
moon_em_bary_sp, _ = sp.spkezr('301', jde_et_secs, 'J2000', "NONE", '3')
# earth_moon_out

# jplephem
s = SPK.open('de438s.bsp')
moon_sg = s.pairs[(3, 301)]
moon_em_bary_jp = moon_sg.compute_and_differentiate(jde_et_days)

print("position delta (km):", moon_em_bary_sp[:3] - moon_em_bary_jp[0])
print("velocity delta (km/s):",
      moon_em_bary_sp[3:] - moon_em_bary_jp[1]/86400.)

Output

> ipython delta.py
position delta (km): [ 1.24332291e-05 -2.63471156e-06 -2.37874337e-06]
velocity delta (km/s): [7.56694707e-12 3.09001713e-11 1.29118383e-11]

Can handle de438t.bsp correctly?

(Please excuse my English. This is a question for this project. If there is a better place for this questions, please let me know.)

I found most recent JPL ephemeris DE438t.bsp(SPK file) from ftp://ssd.jpl.nasa.gov/pub/eph/planets/bsp/. jplephem seemed to handle the DE438t.bsp well, opened well and computed heliocentric coordinates of planets well. However I could not know whether jplephem handles DE438t.bsp correctly.

The DE438t ephemeris has 2 differences compared to other JPL ephemeris.

  1. 'TT-TDB' values are integrated. ( ftp://ssd.jpl.nasa.gov/pub/eph/planets/bsp/README.txt )
  2. Uses 576 ephemeris constants, which exceeds the prior maximum number allowed. ( ftp://ssd.jpl.nasa.gov/pub/eph/planets/ascii/de438t/README.txt )

Can jplephem handle DE438t.bsp correctly, despite above two differences?

spk.compute_and_differentiate yields incorrect body velocity

I calculated the velosity of Earth Barycenter using jplephem v2.8 with the following code

from jplephem.spk import SPK
import numpy
kernel = SPK.open('de430.bsp')
jd = 2458502.4374 # 2019-01-18 80991.266 second of day (UT)
rEarth_bc, vEarth_bc = kernel[0,3].compute_and_differentiate(jd)  
vEarth_bc_abs = numpy.linalg.norm(vEarth_bc)*1e-5

and got velosity modulus vEarth_bc_abs of about 26.162 km/s which is inconsistent with the real value,
see the table below for comparison with Horizons (https://ssd.jpl.nasa.gov/horizons.cgi).

I have cheked the SPK.generate (called by SPK.compute_and_differentiate) function in jplephem/spk.py
and found that the Chebyshev differentiation seems to be incorrect.
The following code gives the velosity of Earth Barycenter consistent with Horizons values (the original code is commented and marked as #original):

  # Chebyshev differentiation.

  dT = empty_like(T)
  dT[0] = 0.0
  dT[1] = 1.0
  if coefficient_count > 2:
      dT[2] = twot1 + twot1
      for i in range(3, coefficient_count):
          #dT[i] = twot1 * dT[i-1] - dT[i-2] + T[i-1] + T[i-1] # original
          dT[i] = 2* (T[i-1] + t1 * dT[i-1]) - dT[i-2] # my
  
  #dT *= 2.0 # original
  #dT /= interval_length # original
  dT /= interval_length / 2 * 86400.0 # my, rates in km/s
  
  rates = (dT.T * coefficients).sum(axis=2)
  if scalar:
      rates = rates[:,0]

  yield rates
vEarth_bc km/s:             Vx                    Vy                    Vz                (Vx**2+Vy**2+Vz**2)**0.5
jplephem v 2.8:     -2.309729719622553E+01 -1.127415751194369E+01 -4.886930526926653E+00 26.1624512488775
Horizons:           -2.673298259309668E+01 -1.304879388205261E+01 -5.656169793123461E+00 30.280614868719987
jplephem corrected: -2.673298286600176E+01 -1.304879341660150E+01 -5.656169591350293E+00 30.280614871385986

Error on travis-ci

Hi, our package PINT depends on jplephem via astropy. Recently, we've been getting some errors in our travis test suite. Strangely, it is happening in Python 3.7 but not Python 3.6 or Python 3.8. Here is what the error looks like:

_______________________ TestTDBMethod.test_astropy_ephem _______________________
self = <test_TDB_method.TestTDBMethod testMethod=test_astropy_ephem>
    def test_astropy_ephem(self):
>       t_astropy = toa.get_TOAs(self.tim, ephem="DE436t")
/home/travis/build/paulray/PINT/tests/test_TDB_method.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/pint/toa.py:114: in get_TOAs
    t.compute_posvels(ephem, planets)
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/pint/toa.py:1427: in compute_posvels
    ssb_obs = site.posvel(tdb, ephem)
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/pint/observatory/topo_obs.py:329: in posvel
    earth_pv = objPosVel_wrt_SSB("earth", t, ephem)
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/pint/solar_system_ephemerides.py:232: in objPosVel_wrt_SSB
    pos, vel = coor.get_body_barycentric_posvel(objname, t)
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/astropy/coordinates/solar_system.py:337: in get_body_barycentric_posvel
    return _get_body_barycentric_posvel(body, time, ephemeris)
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/astropy/coordinates/solar_system.py:292: in _get_body_barycentric_posvel
    spk.generate(jd1, jd2)):
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/jplephem/spk.py:218: in generate
    self._data = data = self._load()
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/jplephem/spk.py:176: in _load
    init, intlen, rsize, n = self.daf.read_array(self.end_i - 3, self.end_i)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <jplephem.daf.DAF object at 0x7f75636d4310>, start = 11957597
end = 11957600
    def read_array(self, start, end):
        """Return floats from `start` to `end` inclusive, indexed from 1.
    
        The entire range of floats is immediately read into memory from
        the file, making this efficient for small sequences of floats
        whose values are all needed immediately.
    
        """
        f = self.file
        f.seek(8 * (start - 1))
        length = 1 + end - start
        data = f.read(8 * length)
>       return ndarray(length, self.endian + 'd', data)
E       TypeError: buffer is too small for requested array
/home/travis/virtualenv/python3.7.6/lib/python3.7/site-packages/jplephem/daf.py:147: TypeError
----------------------------- Captured stdout call -----------------------------

Any chance that rings a bell?

Test failure on BE architectures

The rest suite of jplephem seems to fail on bigendian machines.
On a s390x machine we have the following error

=== python3.10 ===
============================= test session starts ==============================
platform linux -- Python 3.10.6, pytest-7.1.2, pluggy-1.0.0+repack -- /usr/bin/python3.10
cachedir: .pytest_cache
rootdir: /tmp/autopkgtest-lxc.r516qzx2/downtmp/autopkgtest_tmp
collecting ... collected 46 items / 4 deselected / 42 selected

::TestDAFBytesIO::test_add_segment FAILED                                [  2%]
::TestDAFBytesIO::test_add_segment_when_summary_block_is_full FAILED     [  4%]
::TestDAFBytesIO::test_header PASSED                                     [  7%]
::TestDAFBytesIO::test_segments FAILED                                   [  9%]
::TestDAFRealFile::test_add_segment FAILED                               [ 11%]
::TestDAFRealFile::test_add_segment_when_summary_block_is_full FAILED    [ 14%]
::TestDAFRealFile::test_header PASSED                                    [ 16%]
::TestDAFRealFile::test_segments FAILED                                  [ 19%]
::TestDAFRealFileWithoutMMap::test_add_segment FAILED                    [ 21%]
::TestDAFRealFileWithoutMMap::test_add_segment_when_summary_block_is_full FAILED [ 23%]
::TestDAFRealFileWithoutMMap::test_header PASSED                         [ 26%]
::TestDAFRealFileWithoutMMap::test_segments FAILED                       [ 28%]
::SPKTests::test_array_tdb SKIPPED (the "de421.bsp" SPK file is not ...) [ 30%]
::SPKTests::test_array_tdb_array_tdb2 SKIPPED (the "de421.bsp" SPK f...) [ 33%]
::SPKTests::test_array_tdb_scalar_tdb2 SKIPPED (the "de421.bsp" SPK ...) [ 35%]
::SPKTests::test_ephemeris_end_date SKIPPED (the "de421.bsp" SPK fil...) [ 38%]
::SPKTests::test_jitter SKIPPED (the "de421.bsp" SPK file is not ava...) [ 40%]
::SPKTests::test_loading_array SKIPPED (the "de421.bsp" SPK file is ...) [ 42%]
::SPKTests::test_out_of_range_dates SKIPPED (the "de421.bsp" SPK fil...) [ 45%]
::SPKTests::test_scalar_tdb SKIPPED (the "de421.bsp" SPK file is not...) [ 47%]
::SPKTests::test_scalar_tdb2 SKIPPED (the "de421.bsp" SPK file is no...) [ 50%]
::SPKTests::test_scalar_tdb2_keyword SKIPPED (the "de421.bsp" SPK fi...) [ 52%]
::SPKTests::test_scalar_tdb_array_tdb2 SKIPPED (the "de421.bsp" SPK ...) [ 54%]
::SPKTests::test_scalar_tdb_keyword SKIPPED (the "de421.bsp" SPK fil...) [ 57%]
::SPKTests::test_segment_with_only_two_coefficients SKIPPED (the "de...) [ 59%]
::SPKTests::test_str SKIPPED (the "de421.bsp" SPK file is not available) [ 61%]
::SPKTests::test_too_early_date SKIPPED (the "de421.bsp" SPK file is...) [ 64%]
::SPKTests::test_too_late_date SKIPPED (the "de421.bsp" SPK file is ...) [ 66%]
::LegacyTests::test_array_tdb SKIPPED (the "de421" ephemeris package...) [ 69%]
::LegacyTests::test_array_tdb_array_tdb2 SKIPPED (the "de421" epheme...) [ 71%]
::LegacyTests::test_array_tdb_scalar_tdb2 SKIPPED (the "de421" ephem...) [ 73%]
::LegacyTests::test_ephemeris_end_date SKIPPED (the "de421" ephemeri...) [ 76%]
::LegacyTests::test_jitter SKIPPED (the "de421" ephemeris package ha...) [ 78%]
::LegacyTests::test_legacy_compute_method SKIPPED (the "de421" ephem...) [ 80%]
::LegacyTests::test_names SKIPPED (the "de421" ephemeris package has...) [ 83%]
::LegacyTests::test_scalar_tdb SKIPPED (the "de421" ephemeris packag...) [ 85%]
::LegacyTests::test_scalar_tdb2 SKIPPED (the "de421" ephemeris packa...) [ 88%]
::LegacyTests::test_scalar_tdb2_keyword SKIPPED (the "de421" ephemer...) [ 90%]
::LegacyTests::test_scalar_tdb_array_tdb2 SKIPPED (the "de421" ephem...) [ 92%]
::LegacyTests::test_scalar_tdb_keyword SKIPPED (the "de421" ephemeri...) [ 95%]
::LegacyTests::test_too_early_date SKIPPED (the "de421" ephemeris pa...) [ 97%]
::LegacyTests::test_too_late_date SKIPPED (the "de421" ephemeris pac...) [100%]

=================================== FAILURES ===================================
_______________________ TestDAFBytesIO.test_add_segment ________________________

self = <jplephem.test.TestDAFBytesIO testMethod=test_add_segment>

    def test_add_segment(self):
        f = self.sample_daf()
        d = DAF(f)
    
        d.add_array(b'Summary Name 3', (121.0, 232.0, 343), [3003.0] * 128)
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 3)
E       AssertionError: 0 != 3

/usr/lib/python3/dist-packages/jplephem/test.py:143: AssertionError
__________ TestDAFBytesIO.test_add_segment_when_summary_block_is_full __________

self = <jplephem.test.TestDAFBytesIO testMethod=test_add_segment_when_summary_block_is_full>

    def test_add_segment_when_summary_block_is_full(self):
        f = self.sample_daf()
        d = DAF(f)
    
        # Update n_summaries of final summary block to full.
        d.file.seek(6 * 1024 + 16)
        d.file.write(Struct('d').pack(d.summaries_per_record))
    
        d.add_array(b'Summary Name 3', (121.0, 232.0, 343), [3003.0] * 200)
    
        # Reset n_summaries of that block back to its real value.
        d.file.seek(6 * 1024 + 16)
        d.file.write(Struct('d').pack(1))
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 3)
E       AssertionError: 0 != 3

/usr/lib/python3/dist-packages/jplephem/test.py:169: AssertionError
_________________________ TestDAFBytesIO.test_segments _________________________

self = <jplephem.test.TestDAFBytesIO testMethod=test_segments>

    def test_segments(self):
        f = self.sample_daf()
        d = DAF(f)
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 2)
E       AssertionError: 0 != 2

/usr/lib/python3/dist-packages/jplephem/test.py:127: AssertionError
_______________________ TestDAFRealFile.test_add_segment _______________________

self = <jplephem.test.TestDAFRealFile testMethod=test_add_segment>

    def test_add_segment(self):
        f = self.sample_daf()
        d = DAF(f)
    
        d.add_array(b'Summary Name 3', (121.0, 232.0, 343), [3003.0] * 128)
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 3)
E       AssertionError: 0 != 3

/usr/lib/python3/dist-packages/jplephem/test.py:143: AssertionError
_________ TestDAFRealFile.test_add_segment_when_summary_block_is_full __________

self = <jplephem.test.TestDAFRealFile testMethod=test_add_segment_when_summary_block_is_full>

    def test_add_segment_when_summary_block_is_full(self):
        f = self.sample_daf()
        d = DAF(f)
    
        # Update n_summaries of final summary block to full.
        d.file.seek(6 * 1024 + 16)
        d.file.write(Struct('d').pack(d.summaries_per_record))
    
        d.add_array(b'Summary Name 3', (121.0, 232.0, 343), [3003.0] * 200)
    
        # Reset n_summaries of that block back to its real value.
        d.file.seek(6 * 1024 + 16)
        d.file.write(Struct('d').pack(1))
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 3)
E       AssertionError: 0 != 3

/usr/lib/python3/dist-packages/jplephem/test.py:169: AssertionError
________________________ TestDAFRealFile.test_segments _________________________

self = <jplephem.test.TestDAFRealFile testMethod=test_segments>

    def test_segments(self):
        f = self.sample_daf()
        d = DAF(f)
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 2)
E       AssertionError: 0 != 2

/usr/lib/python3/dist-packages/jplephem/test.py:127: AssertionError
_________________ TestDAFRealFileWithoutMMap.test_add_segment __________________

self = <jplephem.test.TestDAFRealFileWithoutMMap testMethod=test_add_segment>

    def test_add_segment(self):
        f = self.sample_daf()
        d = DAF(f)
    
        d.add_array(b'Summary Name 3', (121.0, 232.0, 343), [3003.0] * 128)
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 3)
E       AssertionError: 0 != 3

/usr/lib/python3/dist-packages/jplephem/test.py:143: AssertionError
____ TestDAFRealFileWithoutMMap.test_add_segment_when_summary_block_is_full ____

self = <jplephem.test.TestDAFRealFileWithoutMMap testMethod=test_add_segment_when_summary_block_is_full>

    def test_add_segment_when_summary_block_is_full(self):
        f = self.sample_daf()
        d = DAF(f)
    
        # Update n_summaries of final summary block to full.
        d.file.seek(6 * 1024 + 16)
        d.file.write(Struct('d').pack(d.summaries_per_record))
    
        d.add_array(b'Summary Name 3', (121.0, 232.0, 343), [3003.0] * 200)
    
        # Reset n_summaries of that block back to its real value.
        d.file.seek(6 * 1024 + 16)
        d.file.write(Struct('d').pack(1))
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 3)
E       AssertionError: 0 != 3

/usr/lib/python3/dist-packages/jplephem/test.py:169: AssertionError
___________________ TestDAFRealFileWithoutMMap.test_segments ___________________

self = <jplephem.test.TestDAFRealFileWithoutMMap testMethod=test_segments>

    def test_segments(self):
        f = self.sample_daf()
        d = DAF(f)
    
        summaries = list(d.summaries())
        eq = self.assertEqual
>       eq(len(summaries), 2)
E       AssertionError: 0 != 2

/usr/lib/python3/dist-packages/jplephem/test.py:127: AssertionError
=========================== short test summary info ============================
FAILED ::TestDAFBytesIO::test_add_segment - AssertionError: 0 != 3
FAILED ::TestDAFBytesIO::test_add_segment_when_summary_block_is_full - Assert...
FAILED ::TestDAFBytesIO::test_segments - AssertionError: 0 != 2
FAILED ::TestDAFRealFile::test_add_segment - AssertionError: 0 != 3
FAILED ::TestDAFRealFile::test_add_segment_when_summary_block_is_full - Asser...
FAILED ::TestDAFRealFile::test_segments - AssertionError: 0 != 2
FAILED ::TestDAFRealFileWithoutMMap::test_add_segment - AssertionError: 0 != 3
FAILED ::TestDAFRealFileWithoutMMap::test_add_segment_when_summary_block_is_full
FAILED ::TestDAFRealFileWithoutMMap::test_segments - AssertionError: 0 != 2
============ 9 failed, 3 passed, 30 skipped, 4 deselected in 0.16s =============

See also: https://ci.debian.net/data/autopkgtest/testing/s390x/j/jplephem/25034274/log.gz

Windows Compatibility

daf.py fails in the mmap creation on Windows. I believe a simple change will fix it, changing the offset from PAGESIZE to ALLOCATIONGRANULARITY

https://docs.python.org/2/library/mmap.html
Windows Constructor: "offset may be specified as a non-negative integer offset. mmap references will be relative to the offset from the beginning of the file. offset defaults to 0. offset must be a multiple of the ALLOCATIONGRANULARITY."

Unix Constructor: "offset may be specified as a non-negative integer offset. mmap references will be relative to the offset from the beginning of the file. offset defaults to 0. offset must be a multiple of the PAGESIZE or ALLOCATIONGRANULARITY."

Format question: difference between segment.start_jd and initial_epoch

This might be a file format question, so I understand if you prefer me to offset this to the NAIF team.

In spk.generate, you use the initial epoch to compute the position of the object. In spk.init, you compute the start JD from the start second, which is ephemeris time I believe.

How come there is a difference of 4 days between both values in the de438.bsp file (2415016.5 != 2415020.5)? Similar question for the 3 day difference between the end_jde and the end_second.

Thanks

Ephemeris query for Vesta and Ceres

Hi,
I want to use get_body_barycentric_posvel() for querying the ephemeris for Vesta, Ceres, and some other asteroids.
Do I understand correct, that right now it can only be used for bodies listed by
solar_system_ephemeris.bodies?

Provide close methods?

While implementing support for using jplephem within astropy, @eteq commented that it would be good to close SPK files if they are no longer in use. Obviously, we can do spk.daf.file.close(), but perhaps it would be more elegant to provide a close method to match the open class method, so that one the release of the file remains an implementation detail that could be changed later (if ever necessary).

setup.py uses install_requires but no setuptools

While working on conda-forge/staged-recipes#214 (comment) we discovered that jplephem setup.py is using the option install_requires, which exists only in setuptools.

https://docs.python.org/3/search.html?q=install_requires

https://pythonhosted.org/setuptools/setuptools.html#new-and-changed-setup-keywords

I see also that you are mocking the presence of NumPy, perhaps because of this?

Would you consider using from setuptools import setup instead of plain distutils? Otherwise the install_requires ought to be changed to requires.

https://docs.python.org/3/distutils/setupscript.html#relationships-between-distributions-and-packages

Numpy requirement unclear in metadata

Hi Brandon,

This report is a bit vague, for which I apologize in advance.

In the 2.9 sdist, the include PKG-INFO is metadata 1.1 which has a field Requres, which checks out.

Metadata-Version: 1.1
...
Requires: numpy

If I use pip wheel . (actually as part of further automation) I end up with a wheel whose METADATA file is

Metadata-Version: 2.1
...
Requires: numpy

while it should be Requires-Dist per 1.2 or 2.1 metadata version. Moving the setup.py to use setuptools and changing requires to install_requires makes it produce a consistent metadata

Metadata-Version: 2.1
...
Requires-Dist: numpy

While I suspect this is a bug/interaction in pip or wheel, I'm wondering if there's a specific reason to stay on distutils in 2019?

Version 2.12 doesn't appear to be on conda-forge

When using skyfield to get the sunrise and sunset times for a given datetime, I'm getting an import error regarding the jplephem package.

The following is python code for getting sunrise and sunset.

import datetime
from skyfield import almanac
from skyfield import api
from pytz import timezone
from pytz import utc

ts = api.load.timescale()
e = api.load('de421.bsp')

dt = datetime.datetime.now()
lat = "36.994076 N"
long = "112.974030 W"


sunrise, sunset = get_sunrise_sunset_from_datetime(dt, lat, long)
print(sunrise)
print(sunset)

def get_sunrise_sunset_from_datetime(dt, lat, long):

    bluffton = api.Topos(lat, long)
        
    start_of_day = dt.replace(hour=0, minute=0, second=1)
    start_of_day = start_of_day.astimezone(timezone('UTC'))
    end_of_day = dt.replace(hour=23, minute=59, second=59)
    end_of_day = end_of_day.astimezone(timezone('UTC'))

    t0 = ts.utc(start_of_day)
    t1 = ts.utc(end_of_day)
    t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, bluffton))

    first, first_type = t[0], "Sunset" if y[0] == False else "Sunrise"
    second, second_type = t[1], "Sunset" if y[1] == False else "Sunrise"
    first = first.astimezone(timezone('US/Arizona'))
    second = second.astimezone(timezone('US/Arizona'))
            
    return (first, second) if first_type == "Sunrise" else (second, first)

I'm getting the following error when I try to run the script

Traceback (most recent call last):
  File "skyfieldtest.py", line 3, in <module>
    from skyfield import api
  File "/Users/richardtimpson/opt/anaconda3/lib/python3.7/site-packages/skyfield/api.py", line 14, in <module>
    from .planetarylib import PlanetaryConstants
  File "/Users/richardtimpson/opt/anaconda3/lib/python3.7/site-packages/skyfield/planetarylib.py", line 5, in <module>
    from jplephem.pck import DAF, PCK
ModuleNotFoundError: No module named 'jplephem.pck'

After investigating the jplephem package in my conda installation, I noticed that the pck.py file didn't exist as it does in version 2.12. The version installed in my conda installation is 2.9, and when trying to update the conda package, it didn't do anything.

Running a conda search reveals that only 2.9 is available on conda-forge.

(base) Richards-MacBook-Pro:jplephem richardtimpson$ conda search -c conda-forge plephem
Loading channels: done
No match found for: plephem. Search: *plephem*
# Name                       Version           Build  Channel             
jplephem                         2.5          py27_0  conda-forge         
jplephem                         2.5          py27_1  conda-forge         
jplephem                         2.5          py34_0  conda-forge         
jplephem                         2.5          py35_0  conda-forge         
jplephem                         2.5          py35_1  conda-forge         
jplephem                         2.5          py36_1  conda-forge         
jplephem                         2.6          py27_0  conda-forge         
jplephem                         2.6          py35_0  conda-forge         
jplephem                         2.6          py36_0  conda-forge         
jplephem                         2.7          py27_0  conda-forge         
jplephem                         2.7          py35_0  conda-forge         
jplephem                         2.7          py36_0  conda-forge         
jplephem                         2.7    pyh24bf2e0_1  conda-forge         
jplephem                         2.7    pyh24bf2e0_2  conda-forge         
jplephem                         2.8    pyh11f86e8_0  conda-forge         
jplephem                         2.9    pyh11f86e8_0  conda-forge  

I'm not certain how conda-forge and the packages work, but the latest version isn't there.

Workaround was to copy and paste the pck.py from github to my local copy of jplephem, but it would be nice if the jplephem dependency would automatically update when updating skyfield using conda update.

Velocity units

I found out while playing with DE421 that the velocity units are totally weird:

>>> from jplephem.spk import SPK
>>> segment = SPK.open("/home/juanlu/.poliastro/de421.bsp")[0, 3]
>>> segment.compute_and_differentiate(2455892.12638)
(array([  6.46018928e+07,   1.21419999e+08,   5.26380039e+07]),
 array([-2351289.80926542,  1031820.94826912,   447306.48380103]))

Using a different kernel makes no difference:

>>> segment = SPK.open("/home/juanlu/.poliastro/de430.bsp")[0, 3]
>>> segment.compute_and_differentiate(2455892.12638)
(array([  6.46018929e+07,   1.21419999e+08,   5.26380037e+07]),
 array([-2351289.81068923,  1031820.94419092,   447306.48532802]))

Dividing by 1e5 makes it sensible but that means... centimeters per second? I looked at the original references but found no information about the output units. Looks like a bug to me, what do you think?

Data type 21 and 17 not compatible

Hello.

I tried to use the BSP from the JPL website. Everything goes without worries except for 3 files:

sat393_daphnis.bsp
ura091-rocks-merge.bsp
sat393-rocks_pan.bsp

and the BSPs produced by Horizon telnet.
didymos.bsp

I managed to open them using the jplephem bookstore but it can not read.
it just shows me the number of their type (17 for the 3 cited above and 21 for horizon).

On the other BSP of the JPL that I can read also that on BSP INPOP of immce jplephem me out the number 2 in data_type.

So I would like to know if you know how I can use the 4 SPK bsp that I can not read? (I also tried with spktype01 because jplephem is only compatible with type 2 and 3 but it does not work either).

Ephemerides not pip-installable

It's stated on the PyPI page of the package that the ephemerides can be installed using pip install de421 but this is what I got:

$ pip install de421
Downloading/unpacking de421
  Could not find a version that satisfies the requirement de421 (from versions: 2008)
Cleaning up...
No distributions matching the version for de421

I can still follow the procedure you describe on the README but it's a bit more tedious. pip install de421 is unbeatable :)

jplephem on raspberry pi

Dear Mr. Rhodes,

I received the following error trying to run "python -m jplephem de430.bsp":

...
File "/usr/local/lib/python2.7/dist-packages/jplephem/spk.py", line 38, in __init__
self.segments = [Segment(self.daf, *t) for t in self.daf.summaries()]
AttributeError: 'file' object has no attribute 'summaries'

I got the same error on three different bsp files that I downloaded from NAIF and JPL sites:
de430.bsp, de430_1850-2150.bsp, de405.bsp

I installed jplephem on my Raspberry Pi Model 3 using the following:
"sudo pip install jplephem"
It was an error-free installation.

I first suspected that the file format changed, so I looked for SPACIT or BRIEF executable downloads for Windows or Linux but I could find none.

GitHub will not allow me to attach any of the files since they exceed the 10MB limit.
The smallest, de430_1850-2150.bsp, is only 32MB and downloadable here:
ftp://ssd.jpl.nasa.gov/pub/eph/planets/bsp/

Would you do me a huge favor and see if you can open that file with jplephem? If you can then that tells me that I have a problem on my Pi.

Thank you,
Brian Morgan

Error when opening de405.bsp

I wanted to cross-check the results with the ones that the web interface of HORIZONS provides, but I am unable to open the file with jplephem:

>>> from jplephem.spk import SPK
>>> SPK.open("/home/juanlu/.poliastro/de405.bsp")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/juanlu/.miniconda3/envs/gtoc8/lib/python2.7/site-packages/jplephem/spk.py", line 46, in open
    return cls(open(path, 'rb'))
  File "/home/juanlu/.miniconda3/envs/gtoc8/lib/python2.7/site-packages/jplephem/spk.py", line 39, in __init__
    self.daf = DAF(file_object)
  File "/home/juanlu/.miniconda3/envs/gtoc8/lib/python2.7/site-packages/jplephem/daf.py", line 30, in __init__
    .format(self.locidw, b'DAF/'))
ValueError: file starts with 'NAIF/DAF', not the 4 bytes 'NAIF/DAF'

By the way, it is totally unrelated but I tried to checksum the file and did not found that info online. Are you aware of a public checksum list for SPK files?

jpltest fails for de421

It works nice with de405, but it fails with de421:

$ python -m jplephem.jpltest
de405 AU = 149597870.691 km
  7214 tests successful
de421 AU = 149597870.7 km
Traceback (most recent call last):
  File "/usr/lib/python3.3/runpy.py", line 160, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python3.3/runpy.py", line 73, in _run_code
    exec(code, run_globals)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 111, in <module>
    test_all()
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 106, in test_all
    testpo(ephemeris, testpo_file)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 30, in testpo
    cpos = _position(ephemeris, jed, center)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/jpltest.py", line 77, in _position
    return c('earthmoon', jed) + c('moon', jed) * ephemeris.moon_share
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/ephem.py", line 96, in compute
    bundle = self.compute_bundle(name, tdb, 0.0)
  File "/home/juanlu/.local/lib/python3.3/site-packages/jplephem-1.0-py3.3.egg/jplephem/ephem.py", line 142, in compute_bundle
    % (self.name, jalpha, jomega))
jplephem.ephem.DateError: ephemeris DE421 only covers dates 2414992.5 through 2469808.5

Haven't tried others yet (de421 is not included in the original list). Right now I can't but I might try the other ephemerides as well.

Ability to read INPOP ephemerides

It would be helpful to read the European INPOP ephemerides like INPOP21a:
https://www.imcce.fr/recherche/equipes/asd/inpop/download21a
They claim to make files in the JPL format, but as far as I can tell from a quick look they are not actually compatible. They have different starting data (INPOP21a vs. the DAF/ or NAIF/DAF that jplephem wants) and different structures too.

I don't know how complicated the differences are. I realize that INPOP does provide their own python routines, but we are using astropy which implicitly assumes that the ephemerides will be handled by jplephem, so changes here may be the simplest.

Trying to use excerpt for specific dates without any luck.

I've downloaded the latest jup365.bsp and trying to create an excerpt file for specific dates, but gets errors:

C:\Temp>python -m jplephem excerpt 2021/1/1 2050/12/31 jup365.bsp jup_excerpt.bsp

Traceback (most recent call last):
  File "C:\Program Files\Python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Program Files\Python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\jplephem\__main__.py", line 3, in <module>
    sys.stdout.write(main(sys.argv[1:]))
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\jplephem\commandline.py", line 56, in main
    lines = list(func(args))
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\jplephem\commandline.py", line 93, in excerpt
    write_excerpt(spk, output_file, args.start_date, args.end_date,
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\jplephem\excerpter.py", line 56, in write_excerpt
    excerpt = copy(old.read_array(
  File "C:\Users\admin\AppData\Roaming\Python\Python39\site-packages\jplephem\daf.py", line 146, in read_array
    data = f.read(8 * length)
ValueError: read length must be non-negative or -1

If I specify only 3,5 and 10 targets everything works fine, but not for 501 - 504 or any other targets, or if I do not specify targets at all. Not sure what I'm missing or doing wrong.

bad links on individual ephemeris pages at pypi

Not sure where to mention this, not sure of level of importance either:

on these pages (possibly others):
https://pypi.python.org/pypi/de405
https://pypi.python.org/pypi/de406

There is a broken link to Standish (1998) PDF which looks like this:
http://iau-comm4.jpl.nasa.gov/de405iom/de405iom.pdf

I found a copy of a similar named PDF here:
ftp://ssd.jpl.nasa.gov/pub/eph/planets/ioms/de405.iom.pdf

SImilar situation here:
https://pypi.python.org/pypi/de421

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.