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.
Files changed (71) hide show
  1. astro_burr-0.3.1/.gitignore +52 -0
  2. astro_burr-0.3.1/LICENSE +21 -0
  3. astro_burr-0.3.1/PKG-INFO +217 -0
  4. astro_burr-0.3.1/README.md +174 -0
  5. astro_burr-0.3.1/deploy/example/README.md +44 -0
  6. astro_burr-0.3.1/pyproject.toml +106 -0
  7. astro_burr-0.3.1/src/burr/__init__.py +10 -0
  8. astro_burr-0.3.1/src/burr/bootstrap.py +70 -0
  9. astro_burr-0.3.1/src/burr/cli/__init__.py +0 -0
  10. astro_burr-0.3.1/src/burr/cli/direct.py +126 -0
  11. astro_burr-0.3.1/src/burr/cli/shutdown.py +150 -0
  12. astro_burr-0.3.1/src/burr/cli/sk.py +120 -0
  13. astro_burr-0.3.1/src/burr/cli/sk_bootstrap.py +288 -0
  14. astro_burr-0.3.1/src/burr/core/config.py +444 -0
  15. astro_burr-0.3.1/src/burr/core/constants.py +106 -0
  16. astro_burr-0.3.1/src/burr/core/logging.py +198 -0
  17. astro_burr-0.3.1/src/burr/core/notifications.py +161 -0
  18. astro_burr-0.3.1/src/burr/hardware/device_interface.py +160 -0
  19. astro_burr-0.3.1/src/burr/hardware/direct/device.py +1035 -0
  20. astro_burr-0.3.1/src/burr/hardware/direct/executor.py +361 -0
  21. astro_burr-0.3.1/src/burr/hardware/direct/fits_writer.py +78 -0
  22. astro_burr-0.3.1/src/burr/hardware/direct/notes.txt +5 -0
  23. astro_burr-0.3.1/src/burr/hardware/direct/pwi4_client.py +832 -0
  24. astro_burr-0.3.1/src/burr/hardware/direct/runner.py +346 -0
  25. astro_burr-0.3.1/src/burr/hardware/direct/weather.py +178 -0
  26. astro_burr-0.3.1/src/burr/hardware/factory.py +100 -0
  27. astro_burr-0.3.1/src/burr/hardware/sk/burr_program.py +667 -0
  28. astro_burr-0.3.1/src/burr/hardware/sk/controller.py +296 -0
  29. astro_burr-0.3.1/src/burr/hardware/sk/tasks.py +265 -0
  30. astro_burr-0.3.1/src/burr/hardware/sk/tracking.py +76 -0
  31. astro_burr-0.3.1/src/burr/models/analysis.py +61 -0
  32. astro_burr-0.3.1/src/burr/models/ascom.py +1318 -0
  33. astro_burr-0.3.1/src/burr/models/hardware.py +96 -0
  34. astro_burr-0.3.1/src/burr/models/observation.py +105 -0
  35. astro_burr-0.3.1/src/burr/models/run.py +380 -0
  36. astro_burr-0.3.1/src/burr/models/schedule.py +0 -0
  37. astro_burr-0.3.1/src/burr/models/sensorkit.py +26 -0
  38. astro_burr-0.3.1/src/burr/models/site.py +1446 -0
  39. astro_burr-0.3.1/src/burr/models/tracking.py +120 -0
  40. astro_burr-0.3.1/src/burr/notifications/slack.py +0 -0
  41. astro_burr-0.3.1/src/burr/processing/__init__.py +7 -0
  42. astro_burr-0.3.1/src/burr/processing/service.py +123 -0
  43. astro_burr-0.3.1/src/burr/resources/config/basic.yaml +65 -0
  44. astro_burr-0.3.1/src/burr/resources/data/photometric_standards_landolt2009table.txt +655 -0
  45. astro_burr-0.3.1/src/burr/run/README.md +220 -0
  46. astro_burr-0.3.1/src/burr/run/__init__.py +320 -0
  47. astro_burr-0.3.1/src/burr/run/darks.py +648 -0
  48. astro_burr-0.3.1/src/burr/run/state.py +100 -0
  49. astro_burr-0.3.1/src/burr/run/utils.py +216 -0
  50. astro_burr-0.3.1/src/burr/scheduler/__init__.py +0 -0
  51. astro_burr-0.3.1/src/burr/scheduler/factory.py +99 -0
  52. astro_burr-0.3.1/src/burr/scheduler/scheduler.py +134 -0
  53. astro_burr-0.3.1/src/burr/scheduler/slot.py +134 -0
  54. astro_burr-0.3.1/src/burr/scheduler/strategies.py +210 -0
  55. astro_burr-0.3.1/src/burr/task_source/__init__.py +0 -0
  56. astro_burr-0.3.1/src/burr/task_source/calsats/manager.py +350 -0
  57. astro_burr-0.3.1/src/burr/task_source/coverage/__init__.py +15 -0
  58. astro_burr-0.3.1/src/burr/task_source/coverage/alt_sampling.py +185 -0
  59. astro_burr-0.3.1/src/burr/task_source/coverage/example.py +83 -0
  60. astro_burr-0.3.1/src/burr/task_source/coverage/manager.py +858 -0
  61. astro_burr-0.3.1/src/burr/task_source/flats/__init__.py +0 -0
  62. astro_burr-0.3.1/src/burr/task_source/flats/manager.py +725 -0
  63. astro_burr-0.3.1/src/burr/task_source/lunar/manager.py +490 -0
  64. astro_burr-0.3.1/src/burr/task_source/photometry/catalog.py +316 -0
  65. astro_burr-0.3.1/src/burr/task_source/photometry/manager.py +529 -0
  66. astro_burr-0.3.1/src/burr/task_source/protocol.py +77 -0
  67. astro_burr-0.3.1/src/burr/utils/astro.py +97 -0
  68. astro_burr-0.3.1/src/burr/utils/astropy.py +35 -0
  69. astro_burr-0.3.1/src/burr/utils/ephemeris.py +77 -0
  70. astro_burr-0.3.1/src/burr/utils/spacebook.py +91 -0
  71. 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
@@ -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
+ [![CI](https://github.com/zgazak/burr/actions/workflows/ci.yml/badge.svg)](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
+ [![CI](https://github.com/zgazak/burr/actions/workflows/ci.yml/badge.svg)](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