Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci_cron_weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 17 additions & 6 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 68 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ dependencies = [
"astropy",
"scipy",
"matplotlib",
"arviz",
"arviz-stats",
"arviz-plots",
"corner",
"pymc",
"pandas",
Expand Down
4 changes: 2 additions & 2 deletions pytelpoint/fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import numpy as np

import arviz
import arviz_stats
import pymc as pm

import astropy.units as u
Expand Down Expand Up @@ -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"]
Expand Down
10 changes: 5 additions & 5 deletions pytelpoint/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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