Historical Uranus Residuals: Provenance and Limits

This notebook displays the sourced pre-discovery residuals recorded in the project dataset and documents their provenance. The later illustrative rows and the annual JPL-derived proxy are not historical observations, so they are not used here as evidence that a modern simulation reproduces Le Verrier’s residual curve.

Code
import pandas as pd
from astropy.time import Time
from IPython.display import display

from discoverneptune.data import find_bundled_data_dir
from discoverneptune.plot_style import (
    apply_style,
    dual_render,
    fig_size,
    palette,
    truth_line,
)

apply_style()

1. Load Historical Data

We load the 1846 residuals extracted from Le Verrier’s memoirs. We use the project’s data-loading convention to locate the files.

Code
data_dir = find_bundled_data_dir()
hist_df = pd.read_csv(data_dir / 'leverrier_historical_observations.csv')

# Convert dates to Julian Dates for the integrator
# Note: Astropy Time requires a list or array of strings
hist_df['jd'] = Time(hist_df['date'].tolist()).jd
hist_df.head()
date year observer residual_arcsec type jd
0 1690-12-23 1690 Flamsteed 67.1 ancient 2338676.5
1 1712-03-22 1712 Flamsteed 92.7 ancient 2346435.5
2 1715-03-10 1715 Flamsteed 110.0 ancient 2347518.5
3 1750-09-25 1750 Lemonnier 19.0 ancient 2360501.5
4 1750-10-14 1750 Lemonnier 12.4 ancient 2360520.5

2. Keep Modern Proxy Data Separate

The bundled modern state vectors use JD 2371557.5. They support the separate JPL-derived proxy analysis, but they do not turn the mixed historical CSV into a homogeneous observation series.

Code
print('No modern state-vector overlay is used in this historical evidence plot.')
print('The annual JPL-derived proxy is analyzed separately in validation.ipynb.')
No modern state-vector overlay is used in this historical evidence plot.
The annual JPL-derived proxy is analyzed separately in validation.ipynb.

3. Visualize the Sourced Historical Points

Only rows marked ancient are plotted. Rows marked illustrative encode a pedagogical trend, not measured positions, and are deliberately excluded. A quantitative historical validation requires a separately transcribed and sourced normal-place series.

Code
def _build_historical(hist_df, *, theme="light"):
    import matplotlib.pyplot as plt

    pal = palette(theme)
    fig, ax = plt.subplots(figsize=fig_size("wide"))

    ancient = hist_df[hist_df["type"] == "ancient"]
    ax.plot(
        ancient["year"], ancient["residual_arcsec"], "o",
        label="Ancient observations (Le Verrier 1846)",
        color=pal.before, alpha=0.7,
    )
    truth_line(ax, 0.0, axis="y", theme=theme)
    ax.set_title("Sourced pre-discovery Uranus residuals")
    ax.set_xlabel("Year")
    ax.set_ylabel("Heliocentric longitude residual (arcseconds)")
    ax.legend()
    return fig


display(
    dual_render(
        _build_historical,
        hist_df,
        alt="Sourced pre-discovery Uranus residuals used by Le Verrier",
    )
)