diff --git a/.github/workflows/ci_cron_weekly.yml b/.github/workflows/ci_cron_weekly.yml index 24460a5..8ffbc18 100644 --- a/.github/workflows/ci_cron_weekly.yml +++ b/.github/workflows/ci_cron_weekly.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Python to build docs with sphinx uses: actions/setup-python@v4 with: - python-version: '3.13' + python-version: '3.14' - name: Install base dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 2264ad8..d2b6234 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -24,19 +24,30 @@ jobs: include: - name: Code style checks os: ubuntu-latest - python: '3.13' + python: '3.14' toxenv: codestyle - - name: Python 3.13 with required dependencies and coverage checking + - name: Python 3.14 with required dependencies and coverage checking + os: macos-latest + python: '3.14' + toxenv: py314-test-cov + + - name: Python 3.13 with required dependencies os: macos-latest python: '3.13' - toxenv: py313-test-cov + toxenv: py313-test - - name: Python 3.13 with nightly wheels for key dependencies + - name: Python 3.14 with nightly wheels for key dependencies (macOS) continue-on-error: true os: macos-latest - python: '3.13' - toxenv: py313-test-devdeps + python: '3.14' + toxenv: py314-test-devdeps + + - name: Python 3.14 with nightly wheels for key dependencies (Linux) + continue-on-error: true + os: ubuntu-latest + python: '3.14' + toxenv: py314-test-devdeps steps: - name: Checkout code diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b1740ab --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +`pytelpoint` is a Python library for analyzing telescope pointing performance at the MMT Observatory using Bayesian/probabilistic methods via PyMC. It fits standard TPOINT-compatible pointing models to az/el encoder data. + +## Environment Setup + +```bash +pip install -e ".[test]" +``` + +On macOS, `fitting.py` enforces `/usr/bin/clang++` to avoid conflicts between conda-forge's clang and Xcode command-line tools. + +## Common Commands + +```bash +# Run all tests +pytest --pyargs pytelpoint docs + +# Run a single test file +pytest pytelpoint/tests/test_io.py + +# Run a single test +pytest pytelpoint/tests/test_io.py::test_read_azel_datfile + +# Check code style (max line length 132) +flake8 pytelpoint --count --max-line-length=132 + +# Format code +black pytelpoint + +# Run via tox (uses conda for pymc) +tox -e py313-test + +# Build docs +tox -e build_docs +``` + +## Architecture + +All core modules use `SkyCoord` (AstropY) as the primary data carrier. The typical workflow is: + +1. **IO** (`io.py`): Read pointing run data → returns `(coo_ref, coo_meas)` pair of `SkyCoord` objects in an `AltAz` frame tied to `MMT_LOCATION`. +2. **Stats** (`stats.py`): Compute sky RMS / population SD from coordinate pairs (TPOINT-equivalent diagnostics). +3. **Transform** (`transform.py`): Apply an 8-term az/el pointing model (`azel_model`) analytically to raw encoder coordinates. +4. **Fitting** (`fitting.py`): Fit the pointing model probabilistically using PyMC (`azel_fit`), returning an `arviz.InferenceData` object. `best_fit_pars` summarizes the posterior using `arviz_stats.summary`. +5. **Visualization** (`visualization.py`): `plot_posterior` and `plot_corner` for inspecting PyMC fit results using `arviz_plots`. + +### Pointing model terms (TPOINT-compatible) + +All terms are in arcseconds. The 8 standard az/el terms are: `ia` (az index), `ie` (el index), `an` (N-S axis tilt), `aw` (E-W axis tilt), `ca` (collimation), `npae` (az/el non-perpendicularity), `tf` (tube flexure ∝ cos(el)), `tx` (tube flexure ∝ cot(el)). + +### Key design note + +`fitting.py` uses `pm.math` (Theano/pytensor ops) for the model functions, while `transform.py` uses `numpy` — they implement the same math but for different contexts (PyMC model graph vs. direct application). + +### Test data + +`pytelpoint/test_data/` contains three real pointing run files used in tests. `k_and_e.dat` is the processed (4-column) format; `point_20210821.dat` and `point_20250326.dat` are raw mount code output files. + +## Testing Notes + +- Tests live in `pytelpoint/tests/`. Doctests in `.rst` files under `docs/` are also run. +- `test_mc_fitting` runs a real PyMC MCMC chain (with reduced `nsamp=200, ntune=200`) — it is slow. +- `pytest.ini` options (in `pyproject.toml`) enable `--doctest-rst` and treat most warnings as errors. diff --git a/pyproject.toml b/pyproject.toml index 036a680..2e26635 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,8 @@ dependencies = [ "astropy", "scipy", "matplotlib", - "arviz", + "arviz-stats", + "arviz-plots", "corner", "pymc", "pandas", diff --git a/pytelpoint/fitting.py b/pytelpoint/fitting.py index 3e32203..280b3d5 100644 --- a/pytelpoint/fitting.py +++ b/pytelpoint/fitting.py @@ -3,7 +3,7 @@ import numpy as np -import arviz +import arviz_stats import pymc as pm import astropy.units as u @@ -173,7 +173,7 @@ def best_fit_pars(idata): pointing_pars : dict Best-fit pointing parameters """ - t_fit = arviz.summary(idata, round_to=8) + t_fit = arviz_stats.summary(idata, round_to=8) pointing_pars = {} for p in t_fit.index: pointing_pars[p] = t_fit.loc[p, "mean"] diff --git a/pytelpoint/visualization.py b/pytelpoint/visualization.py index 28bdf43..1a61601 100644 --- a/pytelpoint/visualization.py +++ b/pytelpoint/visualization.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt import corner -import arviz +import arviz_plots import astropy.units as u from astropy.visualization import hist @@ -332,8 +332,8 @@ def plot_posterior(idata): Returns ------- - fig : `matplotlib.figure.Figure` instance - Figure object containing the corner plot. + pc : `~arviz_plots.PlotCollection` + PlotCollection containing the posterior distribution plots. """ - fig = arviz.plot_posterior(idata) - return fig + pc = arviz_plots.plot_dist(idata) + return pc