# dustinspace217/astrowidget architecture

> Architecture diagram of the GitHub repository dustinspace217/astrowidget, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/dustinspace217/astrowidget
- Repository: https://github.com/dustinspace217/astrowidget

## Overview

astrowidget periodically gathers astronomy and weather forecasts for configured sites, scores broadband and narrowband imaging prospects, and publishes shared state for desktop widgets. Its separate calibration workflow records forecasts and user decisions, grades captured FITS sessions, and reports whether the resulting data is sufficient for scoring review. The README documents four widget front ends and the principal forecast capabilities; sampled excerpts confirm fetcher/scoring and calibration links, while unsampled front-end and scoring internals are represented only where documented.

Main entry points: [`fetcher/astrowidget_fetch.py`](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/astrowidget_fetch.py) (Forecast fetcher), [`fetcher/calibration_log.py`](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/calibration_log.py) (Calibration database), [`scoring/lib/scoring/scoring_engine.dart`](https://github.com/dustinspace217/astrowidget/blob/main/scoring/lib/scoring/scoring_engine.dart) (Scoring engine), [`fetcher/allsky_sqm.py`](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/allsky_sqm.py) (All-sky capture)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_forecast["Forecast collection"]
  node_fetcher["Forecast fetcher"]
  node_state["Forecast state"]
  node_notification["Desktop notifications"]
end

subgraph group_score["Scoring"]
  node_score_engine["Scoring engine"]
  node_astro["Astronomy factors"]
  node_weather["Weather factors"]
end

subgraph group_display["Widget presentation"]
  node_plasma["Plasma widget<br/>[main.qml]"]
  node_desktop["Standalone widget<br/>[Main.qml]"]
  node_rainmeter["Rainmeter widget<br/>[AstroWidget.ini]"]
  node_ubersicht["Übersicht widget<br/>[index.jsx]"]
end

subgraph group_calibration["Calibration"]
  node_caldb[("Calibration database<br/>[calibration_log.py]")]
  node_decision["Nightly decision form"]
  node_fits["FITS metrics<br/>[fits_metrics.py]"]
  node_grader["Session grader<br/>[grade.py]"]
  node_readiness["Readiness report"]
  node_allsky["All-sky capture<br/>[allsky_sqm.py]"]
end

node_scheduler(("Scheduled run"))
node_meteo{{"Open-Meteo"}}
node_astrospheric{{"Astrospheric"}}
node_timer{{"7Timer!"}}
node_firms{{"NASA FIRMS"}}
node_user(("Widget user"))
node_camera{{"indi-allsky camera"}}

node_scheduler -->|"starts"| node_fetcher
node_fetcher -->|"fetches weather"| node_meteo
node_fetcher -.->|"fetches optional feed"| node_astrospheric
node_fetcher -->|"fetches fallback data"| node_timer
node_fetcher -.->|"queries fire data"| node_firms
node_fetcher -->|"invokes with forecast"| node_score_engine
node_score_engine -->|"uses astronomy factors"| node_astro
node_score_engine -->|"uses weather factors"| node_weather
node_score_engine -->|"returns verdicts"| node_fetcher
node_fetcher -->|"writes forecast state"| node_state
node_state -->|"read by"| node_plasma
node_state -->|"read by"| node_desktop
node_state -->|"read by"| node_rainmeter
node_state -->|"read by"| node_ubersicht
node_user -->|"views"| node_plasma
node_user -->|"views"| node_desktop
node_user -->|"views"| node_rainmeter
node_user -->|"views"| node_ubersicht
node_fetcher -->|"dispatches alerts"| node_notification
node_fetcher -->|"logs forecasts"| node_caldb
node_user -->|"records outcome"| node_decision
node_decision -->|"writes decisions"| node_caldb
node_fits -->|"supplies metrics"| node_grader
node_grader -->|"writes grades"| node_caldb
node_readiness -->|"reads joined data"| node_caldb
node_allsky -->|"fetches chart data"| node_camera
node_allsky -->|"stores sky readings"| node_caldb

click node_fetcher "https://github.com/dustinspace217/astrowidget/blob/main/fetcher/astrowidget_fetch.py"
click node_score_engine "https://github.com/dustinspace217/astrowidget/blob/main/scoring/lib/scoring/scoring_engine.dart"
click node_astro "https://github.com/dustinspace217/astrowidget/tree/main/scoring/lib/astro"
click node_weather "https://github.com/dustinspace217/astrowidget/tree/main/scoring/lib/weather"
click node_plasma "https://github.com/dustinspace217/astrowidget/blob/main/plasmoid/space.dustin.astrowidget/contents/ui/main.qml"
click node_desktop "https://github.com/dustinspace217/astrowidget/blob/main/desktop/qml/Main.qml"
click node_rainmeter "https://github.com/dustinspace217/astrowidget/blob/main/rainmeter/AstroWidget/AstroWidget.ini"
click node_ubersicht "https://github.com/dustinspace217/astrowidget/blob/main/ubersicht/astrowidget.widget/index.jsx"
click node_notification "https://github.com/dustinspace217/astrowidget/blob/main/fetcher/astrowidget_fetch.py"
click node_caldb "https://github.com/dustinspace217/astrowidget/blob/main/fetcher/calibration_log.py"
click node_decision "https://github.com/dustinspace217/astrowidget/blob/main/forms/nightly_decision.py"
click node_fits "https://github.com/dustinspace217/astrowidget/blob/main/grader/fits_metrics.py"
click node_grader "https://github.com/dustinspace217/astrowidget/blob/main/grader/grade.py"
click node_readiness "https://github.com/dustinspace217/astrowidget/blob/main/grader/calibration_readiness.py"
click node_allsky "https://github.com/dustinspace217/astrowidget/blob/main/fetcher/allsky_sqm.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_fetcher,node_state,node_notification,node_user toneBlue
class node_score_engine,node_astro,node_weather toneAmber
class node_plasma,node_desktop,node_rainmeter,node_ubersicht toneMint
class node_caldb,node_decision,node_fits,node_grader,node_readiness,node_allsky toneRose
class node_scheduler,node_meteo,node_astrospheric,node_timer,node_firms,node_camera toneIndigo
```

## Components

### Forecast collection

- [Forecast fetcher](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/astrowidget_fetch.py): `fetcher/astrowidget_fetch.py`
- **Forecast state**
- [Desktop notifications](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/astrowidget_fetch.py): `fetcher/astrowidget_fetch.py`

### Scoring

- [Scoring engine](https://github.com/dustinspace217/astrowidget/blob/main/scoring/lib/scoring/scoring_engine.dart): `scoring/lib/scoring/scoring_engine.dart`
- [Astronomy factors](https://github.com/dustinspace217/astrowidget/tree/main/scoring/lib/astro): `scoring/lib/astro`
- [Weather factors](https://github.com/dustinspace217/astrowidget/tree/main/scoring/lib/weather): `scoring/lib/weather`

### Widget presentation

- [Plasma widget](https://github.com/dustinspace217/astrowidget/blob/main/plasmoid/space.dustin.astrowidget/contents/ui/main.qml): `plasmoid/space.dustin.astrowidget/contents/ui/main.qml`
- [Standalone widget](https://github.com/dustinspace217/astrowidget/blob/main/desktop/qml/Main.qml): `desktop/qml/Main.qml`
- [Rainmeter widget](https://github.com/dustinspace217/astrowidget/blob/main/rainmeter/AstroWidget/AstroWidget.ini): `rainmeter/AstroWidget/AstroWidget.ini`
- [Übersicht widget](https://github.com/dustinspace217/astrowidget/blob/main/ubersicht/astrowidget.widget/index.jsx): `ubersicht/astrowidget.widget/index.jsx`

### Calibration

- [Calibration database](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/calibration_log.py): `fetcher/calibration_log.py`
- [Nightly decision form](https://github.com/dustinspace217/astrowidget/blob/main/forms/nightly_decision.py): `forms/nightly_decision.py`
- [FITS metrics](https://github.com/dustinspace217/astrowidget/blob/main/grader/fits_metrics.py): `grader/fits_metrics.py`
- [Session grader](https://github.com/dustinspace217/astrowidget/blob/main/grader/grade.py): `grader/grade.py`
- [Readiness report](https://github.com/dustinspace217/astrowidget/blob/main/grader/calibration_readiness.py): `grader/calibration_readiness.py`
- [All-sky capture](https://github.com/dustinspace217/astrowidget/blob/main/fetcher/allsky_sqm.py): `fetcher/allsky_sqm.py`

### Other components

- **Scheduled run**
- **Open-Meteo**
- **Astrospheric**
- **7Timer!**
- **NASA FIRMS**
- **Widget user**
- **indi-allsky camera**

## Connections

- Scheduled run → Forecast fetcher: starts
- Forecast fetcher → Open-Meteo: fetches weather
- Forecast fetcher → Astrospheric: fetches optional feed
- Forecast fetcher → 7Timer!: fetches fallback data
- Forecast fetcher → NASA FIRMS: queries fire data
- Forecast fetcher → Scoring engine: invokes with forecast
- Scoring engine → Astronomy factors: uses astronomy factors
- Scoring engine → Weather factors: uses weather factors
- Scoring engine → Forecast fetcher: returns verdicts
- Forecast fetcher → Forecast state: writes forecast state
- Forecast state → Plasma widget: read by
- Forecast state → Standalone widget: read by
- Forecast state → Rainmeter widget: read by
- Forecast state → Übersicht widget: read by
- Widget user → Plasma widget: views
- Widget user → Standalone widget: views
- Widget user → Rainmeter widget: views
- Widget user → Übersicht widget: views
- Forecast fetcher → Desktop notifications: dispatches alerts
- Forecast fetcher → Calibration database: logs forecasts
- Widget user → Nightly decision form: records outcome
- Nightly decision form → Calibration database: writes decisions
- FITS metrics → Session grader: supplies metrics
- Session grader → Calibration database: writes grades
- Readiness report → Calibration database: reads joined data
- All-sky capture → indi-allsky camera: fetches chart data
- All-sky capture → Calibration database: stores sky readings
