astro-burr 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- astro_burr-0.3.1/.gitignore +52 -0
- astro_burr-0.3.1/LICENSE +21 -0
- astro_burr-0.3.1/PKG-INFO +217 -0
- astro_burr-0.3.1/README.md +174 -0
- astro_burr-0.3.1/deploy/example/README.md +44 -0
- astro_burr-0.3.1/pyproject.toml +106 -0
- astro_burr-0.3.1/src/burr/__init__.py +10 -0
- astro_burr-0.3.1/src/burr/bootstrap.py +70 -0
- astro_burr-0.3.1/src/burr/cli/__init__.py +0 -0
- astro_burr-0.3.1/src/burr/cli/direct.py +126 -0
- astro_burr-0.3.1/src/burr/cli/shutdown.py +150 -0
- astro_burr-0.3.1/src/burr/cli/sk.py +120 -0
- astro_burr-0.3.1/src/burr/cli/sk_bootstrap.py +288 -0
- astro_burr-0.3.1/src/burr/core/config.py +444 -0
- astro_burr-0.3.1/src/burr/core/constants.py +106 -0
- astro_burr-0.3.1/src/burr/core/logging.py +198 -0
- astro_burr-0.3.1/src/burr/core/notifications.py +161 -0
- astro_burr-0.3.1/src/burr/hardware/device_interface.py +160 -0
- astro_burr-0.3.1/src/burr/hardware/direct/device.py +1035 -0
- astro_burr-0.3.1/src/burr/hardware/direct/executor.py +361 -0
- astro_burr-0.3.1/src/burr/hardware/direct/fits_writer.py +78 -0
- astro_burr-0.3.1/src/burr/hardware/direct/notes.txt +5 -0
- astro_burr-0.3.1/src/burr/hardware/direct/pwi4_client.py +832 -0
- astro_burr-0.3.1/src/burr/hardware/direct/runner.py +346 -0
- astro_burr-0.3.1/src/burr/hardware/direct/weather.py +178 -0
- astro_burr-0.3.1/src/burr/hardware/factory.py +100 -0
- astro_burr-0.3.1/src/burr/hardware/sk/burr_program.py +667 -0
- astro_burr-0.3.1/src/burr/hardware/sk/controller.py +296 -0
- astro_burr-0.3.1/src/burr/hardware/sk/tasks.py +265 -0
- astro_burr-0.3.1/src/burr/hardware/sk/tracking.py +76 -0
- astro_burr-0.3.1/src/burr/models/analysis.py +61 -0
- astro_burr-0.3.1/src/burr/models/ascom.py +1318 -0
- astro_burr-0.3.1/src/burr/models/hardware.py +96 -0
- astro_burr-0.3.1/src/burr/models/observation.py +105 -0
- astro_burr-0.3.1/src/burr/models/run.py +380 -0
- astro_burr-0.3.1/src/burr/models/schedule.py +0 -0
- astro_burr-0.3.1/src/burr/models/sensorkit.py +26 -0
- astro_burr-0.3.1/src/burr/models/site.py +1446 -0
- astro_burr-0.3.1/src/burr/models/tracking.py +120 -0
- astro_burr-0.3.1/src/burr/notifications/slack.py +0 -0
- astro_burr-0.3.1/src/burr/processing/__init__.py +7 -0
- astro_burr-0.3.1/src/burr/processing/service.py +123 -0
- astro_burr-0.3.1/src/burr/resources/config/basic.yaml +65 -0
- astro_burr-0.3.1/src/burr/resources/data/photometric_standards_landolt2009table.txt +655 -0
- astro_burr-0.3.1/src/burr/run/README.md +220 -0
- astro_burr-0.3.1/src/burr/run/__init__.py +320 -0
- astro_burr-0.3.1/src/burr/run/darks.py +648 -0
- astro_burr-0.3.1/src/burr/run/state.py +100 -0
- astro_burr-0.3.1/src/burr/run/utils.py +216 -0
- astro_burr-0.3.1/src/burr/scheduler/__init__.py +0 -0
- astro_burr-0.3.1/src/burr/scheduler/factory.py +99 -0
- astro_burr-0.3.1/src/burr/scheduler/scheduler.py +134 -0
- astro_burr-0.3.1/src/burr/scheduler/slot.py +134 -0
- astro_burr-0.3.1/src/burr/scheduler/strategies.py +210 -0
- astro_burr-0.3.1/src/burr/task_source/__init__.py +0 -0
- astro_burr-0.3.1/src/burr/task_source/calsats/manager.py +350 -0
- astro_burr-0.3.1/src/burr/task_source/coverage/__init__.py +15 -0
- astro_burr-0.3.1/src/burr/task_source/coverage/alt_sampling.py +185 -0
- astro_burr-0.3.1/src/burr/task_source/coverage/example.py +83 -0
- astro_burr-0.3.1/src/burr/task_source/coverage/manager.py +858 -0
- astro_burr-0.3.1/src/burr/task_source/flats/__init__.py +0 -0
- astro_burr-0.3.1/src/burr/task_source/flats/manager.py +725 -0
- astro_burr-0.3.1/src/burr/task_source/lunar/manager.py +490 -0
- astro_burr-0.3.1/src/burr/task_source/photometry/catalog.py +316 -0
- astro_burr-0.3.1/src/burr/task_source/photometry/manager.py +529 -0
- astro_burr-0.3.1/src/burr/task_source/protocol.py +77 -0
- astro_burr-0.3.1/src/burr/utils/astro.py +97 -0
- astro_burr-0.3.1/src/burr/utils/astropy.py +35 -0
- astro_burr-0.3.1/src/burr/utils/ephemeris.py +77 -0
- astro_burr-0.3.1/src/burr/utils/spacebook.py +91 -0
- astro_burr-0.3.1/src/burr/utils/spacetrack.py +1189 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
wheels/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
*.egg
|
|
13
|
+
.eggs/
|
|
14
|
+
|
|
15
|
+
# Virtual environments
|
|
16
|
+
.venv
|
|
17
|
+
env/
|
|
18
|
+
venv/
|
|
19
|
+
ENV/
|
|
20
|
+
|
|
21
|
+
# uv (libraries do not pin a lockfile)
|
|
22
|
+
uv.lock
|
|
23
|
+
|
|
24
|
+
# Environment / secrets
|
|
25
|
+
.env
|
|
26
|
+
*.env
|
|
27
|
+
|
|
28
|
+
# Test / coverage reports
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.ruff_cache/
|
|
31
|
+
.coverage
|
|
32
|
+
.coverage.*
|
|
33
|
+
coverage.xml
|
|
34
|
+
coverage-*.xml
|
|
35
|
+
junit-*.xml
|
|
36
|
+
htmlcov/
|
|
37
|
+
reports/
|
|
38
|
+
|
|
39
|
+
# Editor / tooling
|
|
40
|
+
.claude/
|
|
41
|
+
.vscode/
|
|
42
|
+
.idea/
|
|
43
|
+
|
|
44
|
+
# Runtime artifacts
|
|
45
|
+
src/burr/resources/cache/
|
|
46
|
+
*.log
|
|
47
|
+
*.tle
|
|
48
|
+
*.bsp
|
|
49
|
+
*.all
|
|
50
|
+
|
|
51
|
+
# OS files
|
|
52
|
+
.DS_Store
|
astro_burr-0.3.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 J. Zachary Gazak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: astro-burr
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Autonomous calibration and observation scheduling for rapid-deploy SDA telescopes
|
|
5
|
+
Project-URL: Homepage, https://github.com/zgazak/burr
|
|
6
|
+
Project-URL: Repository, https://github.com/zgazak/burr
|
|
7
|
+
Project-URL: Issues, https://github.com/zgazak/burr/issues
|
|
8
|
+
Author-email: Zach Gazak <jzg@alum.mit.edu>
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ascom,astronomy,automation,calibration,observatory,scheduling,sda,space domain awareness,telescope
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
16
|
+
Requires-Python: >=3.13
|
|
17
|
+
Requires-Dist: alpyca>=3.1.0
|
|
18
|
+
Requires-Dist: astropy>=7.1.0
|
|
19
|
+
Requires-Dist: deepdiff>=6.7.1
|
|
20
|
+
Requires-Dist: dotenv>=0.9.9
|
|
21
|
+
Requires-Dist: loguru>=0.7.3
|
|
22
|
+
Requires-Dist: matplotlib>=3.10.3
|
|
23
|
+
Requires-Dist: nats-py>=2.7.0
|
|
24
|
+
Requires-Dist: numpy
|
|
25
|
+
Requires-Dist: pydantic>=2.11.5
|
|
26
|
+
Requires-Dist: requests>=2.32.4
|
|
27
|
+
Requires-Dist: scipy>=1.15.3
|
|
28
|
+
Requires-Dist: skyfield>=1.53
|
|
29
|
+
Requires-Dist: timezonefinder>=6.5.9
|
|
30
|
+
Requires-Dist: tqdm>=4.67.1
|
|
31
|
+
Requires-Dist: tzdata
|
|
32
|
+
Requires-Dist: watchdog>=6.0.0
|
|
33
|
+
Provides-Extra: direct
|
|
34
|
+
Requires-Dist: alpyca>=3.1.0; extra == 'direct'
|
|
35
|
+
Provides-Extra: notify
|
|
36
|
+
Requires-Dist: slack-sdk>=3.35.0; extra == 'notify'
|
|
37
|
+
Provides-Extra: senpai
|
|
38
|
+
Requires-Dist: astro-senpai; extra == 'senpai'
|
|
39
|
+
Provides-Extra: sk
|
|
40
|
+
Requires-Dist: aiofile>=3.9.0; extra == 'sk'
|
|
41
|
+
Requires-Dist: sensorkit[alpaca,filesys,pwi4,webapi]>=0.1.3; extra == 'sk'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# Burr
|
|
45
|
+
|
|
46
|
+
[](https://github.com/zgazak/burr/actions/workflows/ci.yml)
|
|
47
|
+
|
|
48
|
+
Taking the grind out of calibration.
|
|
49
|
+
|
|
50
|
+
Autonomous calibration and observation scheduling for rapid-deploy SDA telescopes.
|
|
51
|
+
|
|
52
|
+
Burr converts an observatory into a space domain awareness asset within days of deployment. It autonomously collects twilight flats, photometric standards, calibration satellite passes, sky coverage maps, and lunar background measurements -- all scheduled by lighting condition and time-share priority.
|
|
53
|
+
|
|
54
|
+
Burr is built off of the descriptions in [Gazak et al. 2025, "Rapid Deployment, Calibration, and Training of Optical Observatories for Space Domain Awareness", AMOS Conference](https://amostech.space/year/2025/rapid-deployment-calibration-and-training-of-optical-observatories-for-space-domain-awareness/) -- see [Citation](#citation) below if you use this software.
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- Python 3.13+
|
|
59
|
+
- [uv](https://docs.astral.sh/uv/) package manager (for development installs)
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
Install from PyPI (package name `astro-burr`, imports as `burr`):
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
pip install astro-burr
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Optional extras:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
pip install "astro-burr[sk]" # SensorKit (NATS-based) control
|
|
73
|
+
pip install "astro-burr[direct]" # direct ASCOM hardware control
|
|
74
|
+
pip install "astro-burr[senpai]" # SENPAI image-processing integration
|
|
75
|
+
pip install "astro-burr[notify]" # Slack notifications
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Development install
|
|
79
|
+
|
|
80
|
+
This repo uses [uv](https://docs.astral.sh/uv/). First install uv, then:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
make sync
|
|
84
|
+
source .venv/bin/activate
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Burr separates **where** you observe from **how** you observe:
|
|
90
|
+
|
|
91
|
+
- A **site file** (`deploy/<site>/site.yaml`) describes the observatory: coordinates, ASCOM/PWI4 hardware addresses, SensorKit entity names, notifications.
|
|
92
|
+
- A **mode preset** (`deploy/presets/*.yaml`) describes the observing strategy: which task sources run, exposure ranges, and scheduling balance.
|
|
93
|
+
|
|
94
|
+
You compose them at run time with `--site` + `--preset`. See [`deploy/example/`](deploy/example/) for a worked example and [`deploy/presets/`](deploy/presets/) for the bundled modes (`sda`, `science`, `survey`).
|
|
95
|
+
|
|
96
|
+
| Site section | Purpose |
|
|
97
|
+
| -------------- | --------------------------------------------------------- |
|
|
98
|
+
| `site` | Coordinates and name (timezone auto-detected) |
|
|
99
|
+
| `hardware` | ASCOM device addresses, ports, active flags |
|
|
100
|
+
| `sk` | SensorKit entity names (for `burr-sk`) |
|
|
101
|
+
| `weather` | Rain/humidity thresholds and recovery timers |
|
|
102
|
+
| `notifications`| Slack channel for status updates |
|
|
103
|
+
| `runtime` | Output directory |
|
|
104
|
+
|
|
105
|
+
### Scheduling strategies
|
|
106
|
+
|
|
107
|
+
Each task source has a scheduling strategy:
|
|
108
|
+
|
|
109
|
+
- **`time_share`** -- target percentage of observing time (e.g. photometry 50%, coverage 30%)
|
|
110
|
+
- **`interval`** -- minimum minutes between runs (e.g. calsats every 10 min)
|
|
111
|
+
- **`one_shot`** -- run once per lighting condition (e.g. twilight flats)
|
|
112
|
+
|
|
113
|
+
### Task sources
|
|
114
|
+
|
|
115
|
+
| Source | What it collects | Typical window |
|
|
116
|
+
| ----------------------- | -------------------------------------------------------- | ----------------- |
|
|
117
|
+
| `twilight_flats` | Flat field frames with auto-exposure adjustment | Nautical twilight |
|
|
118
|
+
| `calsats` | Calibration satellite TLE tracking passes | Twilight + night |
|
|
119
|
+
| `photometric_standards` | Landolt standard star observations with streaks | Night |
|
|
120
|
+
| `coverage` | Sparse sky maps (Fibonacci sphere sampling) | Night |
|
|
121
|
+
| `lunar_background` | Background measurements at angular separations from moon | Night |
|
|
122
|
+
|
|
123
|
+
## Quick Start
|
|
124
|
+
|
|
125
|
+
### Direct mode (ASCOM hardware control)
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
burr-direct --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Connects to mount, camera, dome, and weather sensor via ASCOM Alpaca / PWI4. Runs all night autonomously -- opens dome at twilight, schedules observations by priority, closes dome at dawn or if weather deteriorates.
|
|
132
|
+
|
|
133
|
+
### Simulation mode
|
|
134
|
+
|
|
135
|
+
Set hardware devices to `active: false` in your site file (or point them at the bundled ASCOM/PWI4 simulators under [`deploy/`](deploy/)):
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
burr-direct --site deploy/example/site.yaml --preset deploy/presets/survey.yaml
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### SensorKit mode (NATS-based control)
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
burr-sk --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Runs as a SensorKit program/controller pair, integrating with the [SensorKit](https://github.com/sensorkit/sensorkit) agent framework for multi-system orchestration. Requires the `sk` extra. `burr-sk --bootstrap --host <agent>` discovers SK entities + site position from a running agent and emits a `site.yaml` fragment.
|
|
148
|
+
|
|
149
|
+
### Safe shutdown
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
burr-shutdown --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Closes dome, slews to a bright star for verification, parks mount, disconnects.
|
|
156
|
+
|
|
157
|
+
## Project Structure
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
src/burr/
|
|
161
|
+
bootstrap.py # Explicit engine init (no import-time side effects)
|
|
162
|
+
cli/ # CLI entrypoints (direct, shutdown, sk)
|
|
163
|
+
core/ # Config, constants, logging, notifications
|
|
164
|
+
models/ # Pydantic models (tracking, observation, site, run, hardware)
|
|
165
|
+
task_source/ # Observation generators implementing the TaskSource protocol
|
|
166
|
+
scheduler/ # Shared scheduler (strategies, slots, factory)
|
|
167
|
+
hardware/
|
|
168
|
+
factory.py # Device creation from config
|
|
169
|
+
direct/ # ASCOM control (runner, executor, weather monitor)
|
|
170
|
+
sk/ # SensorKit integration (program, controller, tasks)
|
|
171
|
+
run/ # Run state management and persistence
|
|
172
|
+
utils/ # Astronomy, ephemeris, SpaceTrack utilities
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Credentials
|
|
176
|
+
|
|
177
|
+
Burr reads credentials from the environment (or a `.env` file), never from config:
|
|
178
|
+
|
|
179
|
+
- `SPACETRACK_USERNAME` / `SPACETRACK_PASSWORD` -- for SpaceTrack TLE downloads (calsats)
|
|
180
|
+
- `SLACK_BOT_TOKEN` -- for the optional Slack notifications (`notify` extra)
|
|
181
|
+
|
|
182
|
+
## Output
|
|
183
|
+
|
|
184
|
+
Each night produces a run directory at `{output_dir}/{site}_{YYYYMMDD}/`:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
example_20251201/
|
|
188
|
+
data/ # FITS files (flats, science frames, darks)
|
|
189
|
+
plots/ # Coverage maps, lighting schedules
|
|
190
|
+
metadata/ # run_state.json (resumable)
|
|
191
|
+
logs/ # Application logs
|
|
192
|
+
catalogs/ # TLE catalogs
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Runs auto-resume if interrupted. Starting again on the same night picks up where it left off.
|
|
196
|
+
|
|
197
|
+
## Citation
|
|
198
|
+
|
|
199
|
+
Burr implements the system described in:
|
|
200
|
+
|
|
201
|
+
> Gazak, J. Z., Swindle, R., Morales, S., Phelps, M., Iott, K., Blackhurst, E., & Fletcher, J. 2025, "Rapid Deployment, Calibration, and Training of Optical Observatories for Space Domain Awareness", Proceedings of the Advanced Maui Optical and Space Surveillance Technologies (AMOS) Conference. [doi:10.64861/XGPY2184](https://doi.org/10.64861/XGPY2184)
|
|
202
|
+
|
|
203
|
+
If you use Burr in your research, please cite this paper:
|
|
204
|
+
|
|
205
|
+
```bibtex
|
|
206
|
+
@inproceedings{Gazak2025Burr,
|
|
207
|
+
title = {Rapid Deployment, Calibration, and Training of Optical Observatories for Space Domain Awareness},
|
|
208
|
+
author = {Gazak, J. Zachary and Swindle, Ryan and Morales, Sierra and Phelps, Matthew and Iott, Kevin and Blackhurst, Eric and Fletcher, Justin},
|
|
209
|
+
booktitle = {Proceedings of the Advanced Maui Optical and Space Surveillance Technologies (AMOS) Conference},
|
|
210
|
+
year = {2025},
|
|
211
|
+
doi = {10.64861/XGPY2184}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Burr
|
|
2
|
+
|
|
3
|
+
[](https://github.com/zgazak/burr/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Taking the grind out of calibration.
|
|
6
|
+
|
|
7
|
+
Autonomous calibration and observation scheduling for rapid-deploy SDA telescopes.
|
|
8
|
+
|
|
9
|
+
Burr converts an observatory into a space domain awareness asset within days of deployment. It autonomously collects twilight flats, photometric standards, calibration satellite passes, sky coverage maps, and lunar background measurements -- all scheduled by lighting condition and time-share priority.
|
|
10
|
+
|
|
11
|
+
Burr is built off of the descriptions in [Gazak et al. 2025, "Rapid Deployment, Calibration, and Training of Optical Observatories for Space Domain Awareness", AMOS Conference](https://amostech.space/year/2025/rapid-deployment-calibration-and-training-of-optical-observatories-for-space-domain-awareness/) -- see [Citation](#citation) below if you use this software.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- Python 3.13+
|
|
16
|
+
- [uv](https://docs.astral.sh/uv/) package manager (for development installs)
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
Install from PyPI (package name `astro-burr`, imports as `burr`):
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pip install astro-burr
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Optional extras:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pip install "astro-burr[sk]" # SensorKit (NATS-based) control
|
|
30
|
+
pip install "astro-burr[direct]" # direct ASCOM hardware control
|
|
31
|
+
pip install "astro-burr[senpai]" # SENPAI image-processing integration
|
|
32
|
+
pip install "astro-burr[notify]" # Slack notifications
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Development install
|
|
36
|
+
|
|
37
|
+
This repo uses [uv](https://docs.astral.sh/uv/). First install uv, then:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
make sync
|
|
41
|
+
source .venv/bin/activate
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Configuration
|
|
45
|
+
|
|
46
|
+
Burr separates **where** you observe from **how** you observe:
|
|
47
|
+
|
|
48
|
+
- A **site file** (`deploy/<site>/site.yaml`) describes the observatory: coordinates, ASCOM/PWI4 hardware addresses, SensorKit entity names, notifications.
|
|
49
|
+
- A **mode preset** (`deploy/presets/*.yaml`) describes the observing strategy: which task sources run, exposure ranges, and scheduling balance.
|
|
50
|
+
|
|
51
|
+
You compose them at run time with `--site` + `--preset`. See [`deploy/example/`](deploy/example/) for a worked example and [`deploy/presets/`](deploy/presets/) for the bundled modes (`sda`, `science`, `survey`).
|
|
52
|
+
|
|
53
|
+
| Site section | Purpose |
|
|
54
|
+
| -------------- | --------------------------------------------------------- |
|
|
55
|
+
| `site` | Coordinates and name (timezone auto-detected) |
|
|
56
|
+
| `hardware` | ASCOM device addresses, ports, active flags |
|
|
57
|
+
| `sk` | SensorKit entity names (for `burr-sk`) |
|
|
58
|
+
| `weather` | Rain/humidity thresholds and recovery timers |
|
|
59
|
+
| `notifications`| Slack channel for status updates |
|
|
60
|
+
| `runtime` | Output directory |
|
|
61
|
+
|
|
62
|
+
### Scheduling strategies
|
|
63
|
+
|
|
64
|
+
Each task source has a scheduling strategy:
|
|
65
|
+
|
|
66
|
+
- **`time_share`** -- target percentage of observing time (e.g. photometry 50%, coverage 30%)
|
|
67
|
+
- **`interval`** -- minimum minutes between runs (e.g. calsats every 10 min)
|
|
68
|
+
- **`one_shot`** -- run once per lighting condition (e.g. twilight flats)
|
|
69
|
+
|
|
70
|
+
### Task sources
|
|
71
|
+
|
|
72
|
+
| Source | What it collects | Typical window |
|
|
73
|
+
| ----------------------- | -------------------------------------------------------- | ----------------- |
|
|
74
|
+
| `twilight_flats` | Flat field frames with auto-exposure adjustment | Nautical twilight |
|
|
75
|
+
| `calsats` | Calibration satellite TLE tracking passes | Twilight + night |
|
|
76
|
+
| `photometric_standards` | Landolt standard star observations with streaks | Night |
|
|
77
|
+
| `coverage` | Sparse sky maps (Fibonacci sphere sampling) | Night |
|
|
78
|
+
| `lunar_background` | Background measurements at angular separations from moon | Night |
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
### Direct mode (ASCOM hardware control)
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
burr-direct --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Connects to mount, camera, dome, and weather sensor via ASCOM Alpaca / PWI4. Runs all night autonomously -- opens dome at twilight, schedules observations by priority, closes dome at dawn or if weather deteriorates.
|
|
89
|
+
|
|
90
|
+
### Simulation mode
|
|
91
|
+
|
|
92
|
+
Set hardware devices to `active: false` in your site file (or point them at the bundled ASCOM/PWI4 simulators under [`deploy/`](deploy/)):
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
burr-direct --site deploy/example/site.yaml --preset deploy/presets/survey.yaml
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### SensorKit mode (NATS-based control)
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
burr-sk --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Runs as a SensorKit program/controller pair, integrating with the [SensorKit](https://github.com/sensorkit/sensorkit) agent framework for multi-system orchestration. Requires the `sk` extra. `burr-sk --bootstrap --host <agent>` discovers SK entities + site position from a running agent and emits a `site.yaml` fragment.
|
|
105
|
+
|
|
106
|
+
### Safe shutdown
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
burr-shutdown --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Closes dome, slews to a bright star for verification, parks mount, disconnects.
|
|
113
|
+
|
|
114
|
+
## Project Structure
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
src/burr/
|
|
118
|
+
bootstrap.py # Explicit engine init (no import-time side effects)
|
|
119
|
+
cli/ # CLI entrypoints (direct, shutdown, sk)
|
|
120
|
+
core/ # Config, constants, logging, notifications
|
|
121
|
+
models/ # Pydantic models (tracking, observation, site, run, hardware)
|
|
122
|
+
task_source/ # Observation generators implementing the TaskSource protocol
|
|
123
|
+
scheduler/ # Shared scheduler (strategies, slots, factory)
|
|
124
|
+
hardware/
|
|
125
|
+
factory.py # Device creation from config
|
|
126
|
+
direct/ # ASCOM control (runner, executor, weather monitor)
|
|
127
|
+
sk/ # SensorKit integration (program, controller, tasks)
|
|
128
|
+
run/ # Run state management and persistence
|
|
129
|
+
utils/ # Astronomy, ephemeris, SpaceTrack utilities
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Credentials
|
|
133
|
+
|
|
134
|
+
Burr reads credentials from the environment (or a `.env` file), never from config:
|
|
135
|
+
|
|
136
|
+
- `SPACETRACK_USERNAME` / `SPACETRACK_PASSWORD` -- for SpaceTrack TLE downloads (calsats)
|
|
137
|
+
- `SLACK_BOT_TOKEN` -- for the optional Slack notifications (`notify` extra)
|
|
138
|
+
|
|
139
|
+
## Output
|
|
140
|
+
|
|
141
|
+
Each night produces a run directory at `{output_dir}/{site}_{YYYYMMDD}/`:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
example_20251201/
|
|
145
|
+
data/ # FITS files (flats, science frames, darks)
|
|
146
|
+
plots/ # Coverage maps, lighting schedules
|
|
147
|
+
metadata/ # run_state.json (resumable)
|
|
148
|
+
logs/ # Application logs
|
|
149
|
+
catalogs/ # TLE catalogs
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Runs auto-resume if interrupted. Starting again on the same night picks up where it left off.
|
|
153
|
+
|
|
154
|
+
## Citation
|
|
155
|
+
|
|
156
|
+
Burr implements the system described in:
|
|
157
|
+
|
|
158
|
+
> Gazak, J. Z., Swindle, R., Morales, S., Phelps, M., Iott, K., Blackhurst, E., & Fletcher, J. 2025, "Rapid Deployment, Calibration, and Training of Optical Observatories for Space Domain Awareness", Proceedings of the Advanced Maui Optical and Space Surveillance Technologies (AMOS) Conference. [doi:10.64861/XGPY2184](https://doi.org/10.64861/XGPY2184)
|
|
159
|
+
|
|
160
|
+
If you use Burr in your research, please cite this paper:
|
|
161
|
+
|
|
162
|
+
```bibtex
|
|
163
|
+
@inproceedings{Gazak2025Burr,
|
|
164
|
+
title = {Rapid Deployment, Calibration, and Training of Optical Observatories for Space Domain Awareness},
|
|
165
|
+
author = {Gazak, J. Zachary and Swindle, Ryan and Morales, Sierra and Phelps, Matthew and Iott, Kevin and Blackhurst, Eric and Fletcher, Justin},
|
|
166
|
+
booktitle = {Proceedings of the Advanced Maui Optical and Space Surveillance Technologies (AMOS) Conference},
|
|
167
|
+
year = {2025},
|
|
168
|
+
doi = {10.64861/XGPY2184}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Example deployment
|
|
2
|
+
|
|
3
|
+
A worked example of a Burr site, meant to be copied and edited for a real
|
|
4
|
+
observatory.
|
|
5
|
+
|
|
6
|
+
Burr splits configuration into two pieces:
|
|
7
|
+
|
|
8
|
+
- **`site.yaml`** (here) — *where* and *what*: coordinates, ASCOM/PWI4 hardware
|
|
9
|
+
addresses, SensorKit entity names, weather thresholds, notifications.
|
|
10
|
+
- **a mode preset** (`../presets/*.yaml`) — *how*: which task sources run,
|
|
11
|
+
exposure ranges, and the scheduling balance between them.
|
|
12
|
+
|
|
13
|
+
They are combined at run time, with the preset deep-merged on top of the site
|
|
14
|
+
file.
|
|
15
|
+
|
|
16
|
+
## Run it
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
# SensorKit (NATS-based) control — requires the `sk` extra
|
|
20
|
+
burr-sk --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
21
|
+
|
|
22
|
+
# Direct ASCOM hardware control
|
|
23
|
+
burr-direct --site deploy/example/site.yaml --preset deploy/presets/survey.yaml
|
|
24
|
+
|
|
25
|
+
# Safe shutdown
|
|
26
|
+
burr-shutdown --site deploy/example/site.yaml --preset deploy/presets/sda.yaml
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Make your own
|
|
30
|
+
|
|
31
|
+
1. Copy this directory: `cp -r deploy/example deploy/<your-site>`.
|
|
32
|
+
2. Edit `site.yaml`:
|
|
33
|
+
- set `site.name`, `latitude`, `longitude`, `altitude_km`;
|
|
34
|
+
- set the `hardware` addresses (or `active: false` to simulate a device);
|
|
35
|
+
- for `burr-sk`, fill in the `sk` entity names — discover them with
|
|
36
|
+
`burr-sk --bootstrap --host <agent-host>`;
|
|
37
|
+
- enable `notifications` and set `SLACK_BOT_TOKEN` if you want Slack updates.
|
|
38
|
+
3. Pick (or write) a preset in `../presets/` and run with `--site` + `--preset`.
|
|
39
|
+
|
|
40
|
+
## Simulators
|
|
41
|
+
|
|
42
|
+
The bundled `deploy/ASCOM.Alpaca.Simulators` and `deploy/PWI4` Docker setups let
|
|
43
|
+
you exercise the full pipeline without real hardware — point the `hardware`
|
|
44
|
+
addresses in `site.yaml` at them.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "astro-burr"
|
|
3
|
+
version = "0.3.1"
|
|
4
|
+
description = "Autonomous calibration and observation scheduling for rapid-deploy SDA telescopes"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name = "Zach Gazak", email = "jzg@alum.mit.edu" },
|
|
9
|
+
]
|
|
10
|
+
keywords = [
|
|
11
|
+
"astronomy",
|
|
12
|
+
"telescope",
|
|
13
|
+
"observatory",
|
|
14
|
+
"space domain awareness",
|
|
15
|
+
"sda",
|
|
16
|
+
"scheduling",
|
|
17
|
+
"calibration",
|
|
18
|
+
"ascom",
|
|
19
|
+
"automation",
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
"Intended Audience :: Science/Research",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Astronomy",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"numpy",
|
|
30
|
+
"astropy>=7.1.0",
|
|
31
|
+
"deepdiff>=6.7.1",
|
|
32
|
+
"dotenv>=0.9.9",
|
|
33
|
+
"loguru>=0.7.3",
|
|
34
|
+
"matplotlib>=3.10.3",
|
|
35
|
+
"pydantic>=2.11.5",
|
|
36
|
+
"requests>=2.32.4",
|
|
37
|
+
"scipy>=1.15.3",
|
|
38
|
+
"skyfield>=1.53",
|
|
39
|
+
"timezonefinder>=6.5.9",
|
|
40
|
+
"tqdm>=4.67.1",
|
|
41
|
+
"watchdog>=6.0.0",
|
|
42
|
+
"nats-py>=2.7.0",
|
|
43
|
+
"alpyca>=3.1.0",
|
|
44
|
+
"tzdata", # Required for Windows timezone support
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://github.com/zgazak/burr"
|
|
49
|
+
Repository = "https://github.com/zgazak/burr"
|
|
50
|
+
Issues = "https://github.com/zgazak/burr/issues"
|
|
51
|
+
|
|
52
|
+
[project.scripts]
|
|
53
|
+
burr-direct = "burr.cli.direct:main"
|
|
54
|
+
burr-shutdown = "burr.cli.shutdown:main"
|
|
55
|
+
burr-sk = "burr.cli.sk:main"
|
|
56
|
+
|
|
57
|
+
[project.optional-dependencies]
|
|
58
|
+
# SensorKit (NATS-based) control. sensorkit is published on PyPI.
|
|
59
|
+
sk = [
|
|
60
|
+
"sensorkit[alpaca,pwi4,filesys,webapi]>=0.1.3",
|
|
61
|
+
"aiofile>=3.9.0",
|
|
62
|
+
]
|
|
63
|
+
# Direct ASCOM hardware control (alpyca is already a core dependency; this
|
|
64
|
+
# extra exists for symmetry and explicit intent).
|
|
65
|
+
direct = [
|
|
66
|
+
"alpyca>=3.1.0",
|
|
67
|
+
]
|
|
68
|
+
# SENPAI image-processing integration.
|
|
69
|
+
senpai = [
|
|
70
|
+
"astro-senpai",
|
|
71
|
+
]
|
|
72
|
+
# Slack notifications.
|
|
73
|
+
notify = [
|
|
74
|
+
"slack-sdk>=3.35.0",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
# uv keeps pydantic on the 2.x line shared with downstream integrations.
|
|
78
|
+
[tool.uv]
|
|
79
|
+
override-dependencies = ["pydantic~=2.10"]
|
|
80
|
+
|
|
81
|
+
[build-system]
|
|
82
|
+
requires = ["hatchling"]
|
|
83
|
+
build-backend = "hatchling.build"
|
|
84
|
+
|
|
85
|
+
[tool.hatch.build.targets.wheel]
|
|
86
|
+
packages = ["src/burr"]
|
|
87
|
+
|
|
88
|
+
[tool.hatch.build.targets.sdist]
|
|
89
|
+
include = [
|
|
90
|
+
"src/burr",
|
|
91
|
+
"README.md",
|
|
92
|
+
"LICENSE",
|
|
93
|
+
"pyproject.toml",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.pytest.ini_options]
|
|
97
|
+
addopts = "-ra -q"
|
|
98
|
+
testpaths = ["tests"]
|
|
99
|
+
|
|
100
|
+
[dependency-groups]
|
|
101
|
+
dev = [
|
|
102
|
+
"ruff>=0.3.0",
|
|
103
|
+
"pytest>=8.3.0",
|
|
104
|
+
"pytest-cov>=5.0.0",
|
|
105
|
+
"genbadge[coverage,tests]>=1.1.3",
|
|
106
|
+
]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
__version__ = version("astro-burr")
|
|
5
|
+
except PackageNotFoundError:
|
|
6
|
+
__version__ = "unknown"
|
|
7
|
+
|
|
8
|
+
# Re-export for backward compatibility - code that calls burr.initialize_engine()
|
|
9
|
+
# or burr.load_environment() will still work.
|
|
10
|
+
from burr.bootstrap import initialize_engine, load_environment # noqa: F401
|