Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for dynamical models and dust syndynes/synchrones. #394

Merged
merged 17 commits into from
Aug 20, 2024

Conversation

mkelley
Copy link
Member

@mkelley mkelley commented Jan 26, 2024

Adds the capability to generate syndynes and synchrones. This PR is essentially four enhancements:

  1. Add State objects to hold particle position, velocity, and time.
  2. Add SPICE-equivalent "ephemeris time" capability to the astropy.time system.
  3. Add the DynamicalModel abstract base class to define an API for solving the equations of motion, and implement a few simple models.
  4. Add SynGenerator and supporting classes which can generate syndynes/synchrones.

Design choices are given below.

State objects

Dynamical state is 3D position, velocity, and time. The sbpy.dynamics.State object encapsulates these quantities using the astropy.coordinates sub-module. State vectors are internally stored as a coordinate frame object with position and velocity data. Example coordinate frame objects are HeliocentricEclipticIAU76, FK5, and ICRS. Some coordinate frames require observation time for transformation to other coordinate frames, e.g., from a heliocentric to a barycentric frame. Time is added to the frame as needed. In addition, sbpy adds an ArbitraryFrame, which is used by default and cannot be converted to other frames.

The state's time attribute is typically an astropy.time.Time object. However, when the ArbitraryFrame is used the state's time attribute may be an astropy.units.Quantity.

Create a State object for a particle at x=2 au, moving with v_y=30 km/s, on 2023 Dec 08:

>>> from astropy.time import Time
>>> import astropy.units as u
>>> from sbpy.dynamics import State
>>>
>>> r = [2, 0, 0] * u.au
>>> v = [0, 30, 0] * u.km / u.s
>>> t = Time("2023-12-08")
>>> comet = State(r, v, t)
>>> comet
<State (<ArbitraryFrame Frame>):
 r
  [2. 0. 0.] AU
 v
  [ 0. 30.  0.] km / s
 t
  2023-12-08 00:00:00.000>

States can also be arrays of states:

>>> len(comet)
1
>>> comets = State([r, r], [v, v], [t, t])
>>> len(comets)
2
>>> comet.r.shape  # [x, y, z]
(3,)
>>> comets.r.shape  # [[x, y, z], [x, y, z]]
(2, 3)

To specify a coordinate frame, use the frame keyword argument:

>>> State(r, v, t, frame="heliocentriceclipticiau76")
<State (<HeliocentricEclipticIAU76 Frame (obstime=2023-12-08 00:00:00.000)>):
 r
  [2. 0. 0.] AU
 v
  [ 0. 30.  0.] km / s
 t
  2023-12-08 00:00:00.000>

Alternative implementations

Initially, State stored its data as r, v, and t arrays. This involved extra code for parameter checking and coordinate transformations. Switching to using BaseCoordinateFrame objects simplified both of these aspects. However, t still must be saved internally, as some coordinate frames do not use time.

State could instead use astropy.coordinates.SkyCoord. SkyCoord can store 3D vectors, but is also designed to accommodate 2D representations and operations on the celestial sphere. Dynamical state must only be 3D. BaseCoordinateFrame data could also be 2D, but is more general and lacks many of SkyCoord's 2D-based convenience methods. I also found confusing SkyCoord's tendency to duplicate position and velocity vectors in its coordinate frame objects:

>>> coords = SkyCoord(ra=1 * u.deg, dec=2 * u.deg, distance=1 * u.au)
>>> coords
<SkyCoord (ICRS): (ra, dec, distance) in (deg, deg, AU)
    (1., 2., 1.)>

>>> coords.frame
<ICRS Coordinate: (ra, dec, distance) in (deg, deg, AU)
    (1., 2., 1.)>

Sub-classing SkyCoord or BaseCoordinateFrame would complicate the State API, especially if SkyCoord was sub-classed, whereas the goal is to keep the API simple.

State could have been based on Ephem. Ephem lacks coordinate frame information. Functionally, this would be similar to saving r, v, and t as their own arrays.

Ephemeris time

NAIF SPICE uses TDB seconds from the J2000 epoch for time coordinates. This is not explicitly supported in astropy.time, so a new SpiceEphemerisTime has been created. By importing the sbpy.time sub-module, it becomes available for use as the format "et":

>>> from astropy.time import Time
>>> import sbpy.time
>>>
>>> j2000 = Time(0, format="et")
>>> j2000.iso
'2000-01-01 12:00:00.000'
>>> Time(759307746.954761, format="et")
<Time object: scale='tdb' format='et' value=759307746.954761>

Dynamical integrations (below) will convert Time objects to ephemeris time.

Dynamical models

A lightweight approach to integrating the equations of motion has been implemented in sbpy.dynamics. The new DynamicalModel abstract base class defines the API and implements solving the equations with scipy.integrate.solve_ivp. The implementation is straightforward if we bump sbpy's minimum supported scipy version from 1.3 to 1.4, which allows for arguments to be passed from solve_ivp to the integrated functions.

solve_ivp keyword arguments, such as solution tolerances, or the choice of integrator, are set during DyanmicalModel initialization. The default arguments were designed for high precision: a relative tolerance of 2.3e-14, use of a function for the Jacobian matrix (as opposed to numerical estimates), and use of the LSODA integrator. All of these may be overridden by the user at the time of initialization.

Inheriting classes provide methods that calculate the derivatives of position and velocity, and the Jacobian matrix. Time is given as a float in units of seconds, and position and velocity as a 6-element array ([x, y, z, v_x, v_y, v_z]) in units of kilometers and kilometers per second.

@abc.abstractclassmethod
def dx_dt(cls, t: float, rv: np.ndarray, *args) -> np.ndarray:
    """Derivative of position and velocity.
    ...
    """

@abc.abstractclassmethod
def df_drv(cls, t: float, rv: np.ndarray, *args) -> np.ndarray:
    """Jacobian matrix, :math:`df/drv`.
    ...
    """

The solution is generated using the solve method, whose arguments are the initial dynamical state and the time at which the solution is desired. Additional arguments for dx_dt and df_drv are possible, and necessary in order to pass the beta parameter for integrations considering radiation pressure.

Three dynamical model implementations are defined, FreeExpansion, SolarGravity, and SolarGravityAndRadiationPressure. The following example integrates a pure-gravitational orbit around the Sun:

>>> import astropy.units as u
>>> from sbpy.dynamics import State, SolarGravity
>>> state = State([1, 0, 0] * u.au, [0, 30, 0] * u.km / u.s, 0 * u.s)
>>> integrator = SolarGravity()
>>> t_final = 1 * u.year
>>> integrator.solve(state, t_final)
<State (<ArbitraryFrame Frame>):
  r
    [ 1.48146925e+08 -2.09358771e+07  0.00000000e+00] km
  v
    [ 4.137801   29.70907176  0.        ] km / s
  t
    1.0 yr>

Syndynes and synchrones

The capability to produce syndynes and synchrones has been added to sbpy.dynamics with the SynGenerator class. A State object is used for the dust source, and dust particle orbits are parameterized using beta, the ratio of the force from solar radiation to the force from solar gravity.

The source object state and dust particle states are integrated using the DynamicalModel framework. The SolarGravityAndRadiationPressure model is used by default, but others may be provided at the time the SynGenerator object is initialized. This framework should allow for more complex problems, such as planetary perturbations, or particle fragmentation, provided a dynamical model can be developed to support them.

>>> r = [2, 0, 0] * u.au
>>> v = [0, 30, 0] * u.km / u.s
>>> t = Time("2023-12-08")
>>> comet = State(r, v, t)
>>> betas = [1, 0.1, 0.01, 0]
>>> ages = np.linspace(0, 100, 26) * u.day
>>> dust = SynGenerator(comet, betas, ages)

The integrated particle states are saved in the particles attribute. However, it is more convenient get the syndynes and synchrones packaged as Syndyne and Synchrone objects, which are specialized State objects:

>>> syndyne = dust.syndyne(0)  # get the first syndyne
>>> len(syndyne)
26
>>> syndyne.x
<Quantity [2.99195741e+08, 2.99284224e+08, 2.99549029e+08, 2.99988249e+08,
           3.00598735e+08, 3.01376158e+08, 3.02315083e+08, 3.03409054e+08,
           3.04650704e+08, 3.06031870e+08, 3.07543713e+08, 3.09176847e+08,
           3.10921470e+08, 3.12767487e+08, 3.14704634e+08, 3.16722591e+08,
           3.18811090e+08, 3.20960013e+08, 3.23159471e+08, 3.25399886e+08,
           3.27672045e+08, 3.29967158e+08, 3.32276893e+08, 3.34593405e+08,
           3.36909361e+08, 3.39217944e+08] km>

If an observer is provided to the SynGenerator object at initialization, then the syndyne/synchrone object will have a coords attribute, which is a SkyCoord object containing the observed coordinates of the syndyne/synchrone test particles.

>>> observer = State([0, 1, 0] * u.km, [30, 0, 0] * u.km / u.s, comet.t)
>>> dust = SynGenerator(comet, betas, ages, observer=observer)
>>> syndyne = dust.syndyne(0)
>>> syndyne.coords # equivalent to: observer.observe(syndyne)
<SkyCoord (ArbitraryFrame): (lon, lat, distance) in (deg, deg, km)
    [(359.99999981, 0., 2.99195741e+08),
     (359.99960848, 0., 2.99284224e+08),
     (359.99687763, 0., 2.99549030e+08),
     (359.98950966, 0., 2.99988254e+08),
     (359.97528925, 0., 3.00598763e+08),
     (359.95212067, 0., 3.01376263e+08),
     (359.91806084, 0., 3.02315392e+08),
     (359.87134702, 0., 3.03409819e+08),
...

Syndynes and synchrones may be converted to Ephem objects. The sbpy DataClass fields were updated to include the beta parameter (beta_rad) and relative time (t_relative).

Alternative implementations

Initially, SynGenerator had a two step process:

>>> dust = SynGenerator(comet, betas, ages)
>>> dust.solve()

The initial states were generated at initialization, and final states by the solve() method. Two steps allows for the initial particle states to be modified by the user before being integrated, e.g., to give them a non-zero ejection velocity. This is still possible in the implemented design, but would be instead addressed by sub-classing and overriding initialize_states:

>>> class AlternativeSynGenerator(SynGenerator):
...     def initialize_states(self):
...         super().initialize_states()
...         # then modify self.initial_states as needed

Other changes

There are some improvements to the activity.dust documentation. Some package infrastructure files have been edited with small improvements. The pytest configuration now respects the options in setup.cfg.

Addresses #19.

@pep8speaks
Copy link

pep8speaks commented Jan 26, 2024

Hello @mkelley! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

Line 27:80: E501 line too long (88 > 79 characters)
Line 38:80: E501 line too long (87 > 79 characters)
Line 75:80: E501 line too long (88 > 79 characters)
Line 126:80: E501 line too long (84 > 79 characters)
Line 189:80: E501 line too long (82 > 79 characters)
Line 484:80: E501 line too long (86 > 79 characters)
Line 496:80: E501 line too long (85 > 79 characters)

Line 76:80: E501 line too long (80 > 79 characters)
Line 234:80: E501 line too long (84 > 79 characters)
Line 246:80: E501 line too long (87 > 79 characters)
Line 264:80: E501 line too long (87 > 79 characters)
Line 334:80: E501 line too long (81 > 79 characters)
Line 340:80: E501 line too long (81 > 79 characters)
Line 346:80: E501 line too long (83 > 79 characters)
Line 894:80: E501 line too long (81 > 79 characters)
Line 960:80: E501 line too long (89 > 79 characters)

Line 432:80: E501 line too long (80 > 79 characters)
Line 438:80: E501 line too long (80 > 79 characters)
Line 442:80: E501 line too long (80 > 79 characters)

Line 53:80: E501 line too long (80 > 79 characters)
Line 92:80: E501 line too long (81 > 79 characters)
Line 190:80: E501 line too long (80 > 79 characters)
Line 225:80: E501 line too long (80 > 79 characters)
Line 286:80: E501 line too long (92 > 79 characters)
Line 311:80: E501 line too long (80 > 79 characters)
Line 344:80: E501 line too long (80 > 79 characters)

Line 32:80: E501 line too long (84 > 79 characters)
Line 55:80: E501 line too long (82 > 79 characters)
Line 58:80: E501 line too long (88 > 79 characters)
Line 79:80: E501 line too long (80 > 79 characters)
Line 128:80: E501 line too long (83 > 79 characters)
Line 137:80: E501 line too long (80 > 79 characters)
Line 140:80: E501 line too long (84 > 79 characters)
Line 142:80: E501 line too long (81 > 79 characters)
Line 298:80: E501 line too long (88 > 79 characters)
Line 415:80: E501 line too long (83 > 79 characters)
Line 418:80: E501 line too long (86 > 79 characters)

Line 43:80: E501 line too long (86 > 79 characters)
Line 57:80: E501 line too long (84 > 79 characters)
Line 135:80: E501 line too long (87 > 79 characters)
Line 196:80: E501 line too long (81 > 79 characters)
Line 199:80: E501 line too long (81 > 79 characters)
Line 220:80: E501 line too long (81 > 79 characters)
Line 268:80: E501 line too long (81 > 79 characters)
Line 297:24: E721 do not compare types, use 'isinstance()'
Line 437:80: E501 line too long (83 > 79 characters)
Line 455:80: E501 line too long (80 > 79 characters)
Line 517:80: E501 line too long (82 > 79 characters)
Line 606:80: E501 line too long (83 > 79 characters)

Line 57:80: E501 line too long (88 > 79 characters)
Line 72:80: E501 line too long (88 > 79 characters)
Line 163:80: E501 line too long (86 > 79 characters)
Line 193:80: E501 line too long (86 > 79 characters)

Line 41:80: E501 line too long (83 > 79 characters)
Line 54:80: E501 line too long (82 > 79 characters)
Line 114:80: E501 line too long (95 > 79 characters)
Line 158:80: E501 line too long (86 > 79 characters)
Line 197:80: E501 line too long (83 > 79 characters)
Line 220:80: E501 line too long (84 > 79 characters)
Line 239:80: E501 line too long (80 > 79 characters)
Line 279:80: E501 line too long (82 > 79 characters)
Line 285:80: E501 line too long (94 > 79 characters)
Line 286:80: E501 line too long (88 > 79 characters)
Line 287:80: E501 line too long (110 > 79 characters)
Line 290:80: E501 line too long (88 > 79 characters)
Line 312:80: E501 line too long (81 > 79 characters)
Line 340:80: E501 line too long (88 > 79 characters)
Line 372:80: E501 line too long (93 > 79 characters)
Line 382:80: E501 line too long (118 > 79 characters)
Line 391:80: E501 line too long (95 > 79 characters)
Line 396:80: E501 line too long (97 > 79 characters)
Line 435:80: E501 line too long (80 > 79 characters)
Line 438:80: E501 line too long (80 > 79 characters)
Line 446:80: E501 line too long (81 > 79 characters)
Line 453:80: E501 line too long (80 > 79 characters)
Line 490:80: E501 line too long (82 > 79 characters)
Line 491:80: E501 line too long (91 > 79 characters)
Line 509:80: E501 line too long (80 > 79 characters)
Line 559:80: E501 line too long (86 > 79 characters)

Line 166:80: E501 line too long (83 > 79 characters)
Line 190:80: E501 line too long (83 > 79 characters)
Line 203:80: E501 line too long (83 > 79 characters)
Line 337:80: E501 line too long (87 > 79 characters)
Line 373:80: E501 line too long (85 > 79 characters)
Line 378:80: E501 line too long (84 > 79 characters)
Line 392:80: E501 line too long (83 > 79 characters)
Line 396:80: E501 line too long (89 > 79 characters)
Line 406:80: E501 line too long (85 > 79 characters)
Line 438:80: E501 line too long (85 > 79 characters)
Line 440:80: E501 line too long (84 > 79 characters)
Line 451:80: E501 line too long (86 > 79 characters)
Line 463:80: E501 line too long (81 > 79 characters)
Line 478:80: E501 line too long (83 > 79 characters)
Line 481:80: E501 line too long (86 > 79 characters)
Line 494:80: E501 line too long (80 > 79 characters)
Line 495:80: E501 line too long (86 > 79 characters)

Line 69:80: E501 line too long (84 > 79 characters)
Line 124:80: E501 line too long (84 > 79 characters)

Comment last updated at 2024-08-20 19:32:27 UTC

Copy link

codecov bot commented Jan 26, 2024

Codecov Report

Attention: Patch coverage is 99.81343% with 2 lines in your changes missing coverage. Please review.

Project coverage is 82.99%. Comparing base (eaff110) to head (057efbc).
Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
sbpy/dynamics/state.py 98.75% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #394      +/-   ##
==========================================
+ Coverage   80.49%   82.99%   +2.49%     
==========================================
  Files          79       88       +9     
  Lines        7070     8108    +1038     
==========================================
+ Hits         5691     6729    +1038     
  Misses       1379     1379              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.


🚨 Try these New Features:

@mkelley
Copy link
Member Author

mkelley commented Jan 26, 2024

@hhsieh00 FYI, readthedocs builds documentation on pull requests (see the "checks" below). For your convenience, the time and dynamics documentation are at:

https://sbpy--394.org.readthedocs.build/en/394/sbpy/time.html
https://sbpy--394.org.readthedocs.build/en/394/sbpy/dynamics.html

@mkelley mkelley force-pushed the syndynes-2024.01.26 branch 2 times, most recently from fd80b56 to 8ecb63f Compare July 23, 2024 01:25
Copy link
Collaborator

@hhsieh00 hhsieh00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been able to run all code in the documentation to completion (on OSX with an Apple M3 chip). The one error I encountered was "SyntaxWarning: invalid escape sequence '('" in sbpy/sbpy/data/names.py:380 when importing State. The errors seem to be in example table in names.py (lines 432, 438, 442) where parentheses in object names are used with leading backslashes. Removing these backslashes resolves the error. @mkelley, can you confirm that this change is okay?

On a separate note, would it be possible to add more to the documentation for adding ejection velocities to dust particles? The "then modify self.initial_states as needed" comment in the documentation is pretty vague and clicking on the link does not show a workable example either.

@mkelley
Copy link
Member Author

mkelley commented Aug 17, 2024

Unfortunately, removing the blackslashes causes Sphinx to interpret those lines as parts of an enumerated list, so "(2001) Einstein" becomes "2001. Einstein". However, we can fix that by following the closing parenthesis with a non-breaking space.

https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#enumerated-lists

@mkelley
Copy link
Member Author

mkelley commented Aug 17, 2024

👍🏻 An example has been added.

Copy link
Collaborator

@hhsieh00 hhsieh00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, all looks good now! I can import State without error now. I also tried implementing the ejection velocity example and was able to get it run, although the example synchrones for a 10km ejection velocity are all way out of frame of the sample plot (keeping everything else the same). Using a 0.01 km sample ejection velocity keeps everything visible within the same dRA,dDec limits, but looks obviously different, so the added velocity clearly makes a difference. So @mkelley, you might want to change the example ejection velocity in the documentation, but otherwise, seems good to go.

test_synchrone_plot_with_delta_v.pdf

@mkelley mkelley force-pushed the syndynes-2024.01.26 branch from c46ed58 to 710a30b Compare August 20, 2024 19:14
mkelley added 14 commits August 20, 2024 15:19
commit ea4465b404778f844f7c573ee93cd0b857d1e8a2
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 13:14:45 2024 -0500

    Update tests for 100% coverage

commit 06f1fc08a1316d68097b03935fb815c9b5bf9e0d
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 12:17:47 2024 -0500

    Reduce State.__repr__ indentation and don't rename repr

commit ddceaf5b9b1bf1227fe90ea82ff678660907d725
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 11:57:07 2024 -0500

    Also save intial state time in Syndyne/Synchrone.to_ephem

commit 0ff4fe381ab7bd877d5325a139131f49d48c7a18
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 11:55:12 2024 -0500

    Automatically run solve() for syndynes.

commit 6b938dc6fcca8247d7f9477aebf1e05fd0fdea5c
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 11:36:56 2024 -0500

    Document how to add ejection velocity to syndynes.

commit 8909e16507342429e15ef846f03c007f72837156
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 11:23:45 2024 -0500

    Add SynGenerator.at_epochs

commit b49b25507e1c2698b1717aaa5650c61402c90ab1
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 10:42:40 2024 -0500

    Move synydnes to dynamics.

commit 239bbb1e51acb00000f695137d3bf7deec75aee9
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 09:15:45 2024 -0500

    Limit relative time to state objects in the arbitrary frame.

commit 72ba4915d4df5c426889d3e9d6e448d5a8e3ca4f
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Fri Jan 26 08:57:28 2024 -0500

    Comment on lack of improvement in State.observe() tests using DE440s

commit 7508f6a
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 25 20:06:25 2024 -0500

    Do not inherit docstrings with autodoc

commit 66a4cf6
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 25 19:50:16 2024 -0500

    Update documentation

commit 09d7163
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 25 19:49:54 2024 -0500

    Only specify pytest options in one file.

commit 78b4848
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 25 17:41:57 2024 -0500

    New Syndyne(s) and Synchrone(s) to encapsulate SynGenerator output.

commit 9ea0913
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 14:04:35 2024 -0500

    Remove misplaced code

commit ddafbbd
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 14:02:11 2024 -0500

    Rename Syndynes to Syn

commit 4d7832d
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 13:57:01 2024 -0500

    Document ephemeris time.

commit 5ceb361
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 12:51:39 2024 -0500

    Passing tests.

commit 2b90a2f
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 11:57:23 2024 -0500

    Fix dynamics doc page title

commit 55ab980
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 11:23:43 2024 -0500

    Move dynamics to sbpy.dynamics

commit ea75b34
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 10:38:13 2024 -0500

    Update documentation.

commit 43c0fd8
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Tue Jan 23 10:15:05 2024 -0500

    Refactor State to internally use astropy's coordinate frames

commit 2bbc29f
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Mon Jan 22 08:42:33 2024 -0500

    Doc updates for dynamics

commit f7ca7f7
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Mon Jan 22 08:42:21 2024 -0500

    Improve handling of frames

commit 27a435b
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Sat Jan 20 11:34:35 2024 -0500

    activity.dust.dyanmics requires scipiy>=1.4 for solve_ivp enhancements

commit 095839d
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 18 16:02:42 2024 -0500

    Allow arbitrary time values as Quantity objects.

commit 0b26d6b
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 18 14:18:26 2024 -0500

    Improve handling of coordinate frames (and None); make State.t a scalar when appropriate

commit b5216fd
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 18 12:56:08 2024 -0500

    Mark required packages for dynamics and syndynes; rename test_comae to test_core

commit d1a5298
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 18 11:25:18 2024 -0500

    Remove doctests for unfinished time_input

commit c4246f0
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 18 11:10:24 2024 -0500

    Remove units from type annotations.

commit 8768aaa
Author: Michael S. P. Kelley <msk@astro.umd.edu>
Date:   Thu Jan 18 10:39:26 2024 -0500

    Squashed commit of the following:

    commit 79a61b0
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sun Dec 10 08:54:21 2023 -0500

        Improve syndyne docs

    commit b14103c
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Dec 9 14:41:04 2023 -0500

        Add posargs to build_docs

    commit ea0f4b9
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Dec 9 14:39:12 2023 -0500

        Document syndynes.

    commit de277d0
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Fri Dec 8 15:24:39 2023 -0500

        Begin syndyne documentation.

    commit 957b604
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Thu Dec 7 15:25:53 2023 -0500

        Remove redundant file.

    commit 03b4e4e
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Thu Dec 7 14:37:42 2023 -0500

        Test syndynes.

    commit b8bf96d
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Thu Dec 7 12:28:31 2023 -0500

        Up coverage

    commit c32cc79
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Dec 6 13:45:40 2023 -0500

        Up coverage.

    commit 803e445
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Dec 6 09:46:27 2023 -0500

        from_ephem working

    commit d812bcf
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Tue Dec 5 23:22:11 2023 -0500

        Drop time requirement on state observe/add/sub

    commit 5cc7ea5
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Tue Dec 5 11:38:34 2023 -0500

        Update testing and coverage

    commit 466b425
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Dec 2 08:24:06 2023 -0500

        Allow alterative solvers; allow users to modify the initial states before solving.

    commit e13ea20
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Dec 2 08:23:41 2023 -0500

        Edit comments, docstring

    commit a9f12ba
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Fri Dec 1 21:31:44 2023 -0500

        Straighten out observations and frame transformations.

    commit e785a13
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Mon Nov 27 19:26:37 2023 -0500

        try using astropy to do frame conversion

    commit 4184ce3
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Nov 25 11:51:39 2023 -0500

        Update default method and tests.

    commit 1143d75
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Nov 25 11:31:07 2023 -0500

        Drop PR drag.

    commit c4917d7
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Nov 25 10:15:25 2023 -0500

        Update state tests.

    commit c8cd8e4
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Sat Nov 25 09:51:28 2023 -0500

        Adjust rtol in solve_ivp and drop max_step calculation.

    commit de9c797
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Thu Nov 23 10:29:29 2023 -0500

        Syndynes and synchrones success.

    commit 4e1734c
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Nov 22 21:19:49 2023 -0500

        Move State testing

    commit df60e37
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Nov 22 21:03:11 2023 -0500

        Slight rearranging.

    commit a84973f
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Nov 22 19:23:46 2023 -0500

        Internally test (and fix) radiation pressure.

    commit 623b98a
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Nov 22 18:32:39 2023 -0500

        Working FreeExpansion and SolarGravity models.

    commit 12a4766
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Tue Nov 21 17:46:09 2023 -0500

        Passing time test.

    commit 9b56df6
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Tue Nov 21 17:12:30 2023 -0500

        New sbpy.time submodule for SpiceEphemerisTime

    commit d404dea
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Mon Nov 20 11:54:59 2023 -0500

        Re-arrange State to __init__ with vectors.

    commit 0be01be
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Aug 3 10:41:18 2022 -0400

        State nearly fully tested.

    commit 460ff58
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Mon Aug 1 20:11:02 2022 -0400

        Saving again.

    commit d285ca4
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Mon Aug 1 07:00:24 2022 -0400

        Checking in.

    commit 6d13b49
    Author: Michael S. P. Kelley <msk@astro.umd.edu>
    Date:   Wed Jul 13 15:18:51 2022 -0400

        Make room for syndynes.
When a leading number enclosed in parentheses starts a single line of
text, it is interpreted as the number of an enumerated list:

  (2001) Einstein

Is rendered by Sphinx as:

  2001. Einstein

Escaping the parentheses avoids the list interpretation, but has
recently resulted in a Python SyntaxWarning:

  SyntaxWarning: invalid escape sequence '('" in sbpy/sbpy/data/names.py:380

Instead, follow the closing parenthesis with a non-breaking space.
@mkelley mkelley force-pushed the syndynes-2024.01.26 branch from 710a30b to 092cd28 Compare August 20, 2024 19:20
@mkelley mkelley merged commit e7f2675 into NASA-Planetary-Science:main Aug 20, 2024
10 checks passed
@mkelley mkelley deleted the syndynes-2024.01.26 branch August 20, 2024 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants