Metadata-Version: 2.4
Name: pytshade
Version: 0.1.0
Summary: Python toolkit for generating StratoScript files for Nightshade planetarium systems
Author: Justin
License-Expression: GPL-3.0-only
Project-URL: Homepage, https://github.com/sidereumcorpus/pytshade
Project-URL: Repository, https://github.com/sidereumcorpus/pytshade
Project-URL: Issues, https://github.com/sidereumcorpus/pytshade/issues
Keywords: planetarium,astronomy,nightshade,stratoscript,digitalis
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Education
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ephem==4.2
Provides-Extra: examples
Requires-Dist: astropy<8,>=6; extra == "examples"
Dynamic: license-file

# pytshade

**Python toolkit for generating StratoScript (.sts) files for [Digitalis](https://www.digitalisprojection.com/) planetarium systems running Nightshade.**

`pytshade` lets you write planetarium shows in Python! Constellations, eclipses, meteor showers, planet tours, etc. and compile them into the linear StratoScript format that Nightshade executes on the dome.

## Features

- **Builder pattern** - chain method calls, then `build()` or `save()` to emit a `.sts` file.
- **Shadow-state tracking** - skips redundant flag/timerate/zoom commands automatically.
- **Version compatibility** - targets **Nightshade NG** (OP3) or **Nightshade Legacy** (11.12.1) with a single `version=` switch.
- **Astronomy helpers** - [PyEphem](https://rhodesmill.org/pyephem/) wrapper for visibility checks, moon phases, eclipse lookups, and sun position calculations.
- **Deterministic resets** - every script starts from a known state via `init_block()` / `reset_to_default()`.
- **Long-pan waypoints** - automatically splits camera pans > 170° on NG to work around SLERP shortest-path behavior.
- **Meteor radiant database** - built-in RA/Dec for Perseids, Geminids, Leonids, Quadrantids, and Orionids.

## Quick Start

```bash
# Clone and install with uv
git clone https://github.com/sidereumcorpus/pytshade.git
cd pytshade
uv sync --group dev
```

If you want the optional astronomy examples as well:

```bash
uv sync --group dev --extra examples
```

```python
import datetime
from pytshade import StratoScriptBuilder

builder = StratoScriptBuilder("location.json")
builder.init_block()

builder.set_date(datetime.datetime.now().replace(hour=21))
builder.flag("atmosphere", False)
builder.constellations(show=True, art=True)
builder.wait(10)
builder.constellations(show=False)
builder.flag("atmosphere", True)

builder.save("my_show.sts")
```

Copy the `.sts` file to `D:\Nightshade\data\scripts\` and run it from the Nightshade script menu.

## uv Workflow

```bash
# Install dependencies
uv sync --group dev

# Run tests
uv run python -m unittest discover -s tests -v

# Run the demo generator
uv run python generate_demo_script.py

# Build distributions
uv build
```

## Project Structure

```
pytshade/
  __init__.py          # Public API: StratoScriptBuilder, AstroHelper, NightshadeVersion
  builder.py           # Public builder import path
  astronomy.py         # Public astronomy import path
  version.py           # Public version import path
digitalis_scripts/
  ...                  # Backward-compatible internal implementation package
examples/
  quickstart.py        # Minimal 30-second constellation demo
  ephem_moon_phases.py # Moon-phase calendar using AstroHelper
  astropy_planet_tour.py  # Planet visibility tour using astropy
  legacy_mode.py       # Targeting Nightshade Legacy syntax
tests/
  test_builder.py      # Builder unit tests (63 tests)
  test_astronomy.py    # AstroHelper unit tests
  test_version.py      # Version profile tests
generate_demo_script.py  # Full 7-scene demo show generator
location.json            # Observer location config
```

## Nightshade Version Targeting

`pytshade` defaults to **Nightshade NG** syntax. To generate scripts for **Legacy 11.12.1**:

```python
from pytshade import StratoScriptBuilder, NightshadeVersion

builder = StratoScriptBuilder("location.json", version=NightshadeVersion.LEGACY)
```

| Feature | NG | Legacy |
|---|---|---|
| Meteors | `meteors ra/dec` + `meteors zhr` | `meteors rate` |
| Video | `video action play` | `external_viewer action play` |
| Movement | SLERP shortest path (auto-split > 170°) | Linear interpolation |

## Using with Other Astronomy Libraries

### PyEphem (built-in)

```python
from pytshade import AstroHelper

astro = AstroHelper(lat="36.53", lon="-87.35", elevation=155)
moon_time = astro.find_good_moon_time(min_phase=0.5)
phase = astro.get_moon_phase(moon_time)
```

### Astropy (optional)

See [examples/astropy_planet_tour.py](examples/astropy_planet_tour.py) for a full working example that uses `astropy.coordinates.get_body()` to check planet altitudes and only visits those above the horizon.

```bash
uv sync --group dev --extra examples
uv run python examples/astropy_planet_tour.py
```

### Skyfield / Other Libraries

`pytshade`'s builder is library-agnostic. Compute positions with any library, then feed the results into the builder:

```python
# Pseudocode - works with skyfield, poliastro, etc.
alt_deg, az_deg = my_library.get_planet_position("Mars", time)
if alt_deg > 0:
    builder.select_planet("Mars")
    builder.flag("track_object", True)
    builder.zoom(fov=10, duration=2)
```

## Running Tests

```bash
uv run python -m unittest discover -s tests -v
```

## Generating the Demo Show

```bash
uv run python generate_demo_script.py
```

This produces 7 individual `.sts` scripts plus a combined full show, copies them to the Nightshade scripts directory, and mirrors them in `generated_scripts/` for version control.

## Key Concepts

### State Reset

Every standalone script should call `builder.init_block()` at the start. This runs `clear` + `reset_to_default()` which:

1. Drops all media (images, video, audio)
2. Deselects objects and stops tracking
3. Returns to Earth at your `location.json` coordinates
4. Resets all flags to sensible defaults
5. Resets view direction, FOV, time, and timerate

### Gotchas

- **`track_object` persists** - always disable it when done tracking.
- **`timerate` persists** - reset to `timerate(1)` at scene end.
- **Meteor showers need FOV 180** - meteors spawn at FOV edges; zooming in means they never enter view. Use ZHR 10000+ for visual density.
- **Solar System Observer** - disable `atmosphere` and `landscape` *before* switching to `"Solar System Observer"`.
- **Long pans on NG** - pans > 170° are automatically split by `pan_to()`, but if you use `set_view()` directly you must handle this yourself.

## Requirements

- Python 3.10+
- [uv](https://docs.astral.sh/uv/)
- [PyEphem](https://rhodesmill.org/pyephem/) 4.x
- [Astropy](https://www.astropy.org/) (optional, for advanced ephemeris examples)

## Publishing

Build locally with:

```bash
uv build
```

Check the artifacts before release:

```bash
uv run python -m twine check dist/*
```

The repo also includes GitHub Actions workflows for:

- CI on pushes and pull requests: [.github/workflows/ci.yml](.github/workflows/ci.yml)
- Publish on GitHub Release: [.github/workflows/publish.yml](.github/workflows/publish.yml)

Before the first real publish, configure PyPI trusted publishing for your repository.

## GitHub Upload

The project can be connected to GitHub with:

```bash
git add .
git commit -m "Initial pytshade release"
git remote add origin https://github.com/sidereumcorpus/pytshade.git
git push -u origin main
```

## Compatibility Note

The new public import path is `pytshade`:

```python
from pytshade import StratoScriptBuilder
```

The older `digitalis_scripts` imports still work for now so existing scripts do not break immediately.

## License

GNU General Public License v3.0 only (GPL-3.0-only). See [LICENSE](LICENSE).
