Python toolkit for generating StratoScript files for Nightshade planetarium systems
Project description
pytshade
Python toolkit for generating StratoScript (.sts) files for Digitalis 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()orsave()to emit a.stsfile. - 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 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
# 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:
uv sync --group dev --extra examples
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
# 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:
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)
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 for a full working example that uses astropy.coordinates.get_body() to check planet altitudes and only visits those above the horizon.
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:
# 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
uv run python -m unittest discover -s tests -v
Generating the Demo Show
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:
- Drops all media (images, video, audio)
- Deselects objects and stops tracking
- Returns to Earth at your
location.jsoncoordinates - Resets all flags to sensible defaults
- Resets view direction, FOV, time, and timerate
Gotchas
track_objectpersists - always disable it when done tracking.timeratepersists - reset totimerate(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
atmosphereandlandscapebefore switching to"Solar System Observer". - Long pans on NG - pans > 170° are automatically split by
pan_to(), but if you useset_view()directly you must handle this yourself.
Requirements
Publishing
Build locally with:
uv build
Check the artifacts before release:
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
- Publish on GitHub Release: .github/workflows/publish.yml
Before the first real publish, configure PyPI trusted publishing for your repository.
To publish a release, bump the package version, create a matching vX.Y.Z tag, push the tag, and then create a GitHub release for that tag.
Compatibility Note
The new public import path is pytshade:
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytshade-0.1.2.tar.gz.
File metadata
- Download URL: pytshade-0.1.2.tar.gz
- Upload date:
- Size: 34.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fcfc31dc0a43040a3b74d3d0d914f279f942c4db98440918764c1763297b0993
|
|
| MD5 |
587c0d22526ec706a79e8088fdb9b144
|
|
| BLAKE2b-256 |
31b7d3ee66d968af410024e17a9c011a608f8a6f6a097fe76b0975a6afbcdc35
|
File details
Details for the file pytshade-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pytshade-0.1.2-py3-none-any.whl
- Upload date:
- Size: 30.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13d9e1ecacc46e132b82e999db32fb9c686da4b0ffd765f35d73bb01695892bd
|
|
| MD5 |
5a147a53fbe5a5fe12511f57318ea0ab
|
|
| BLAKE2b-256 |
0d82b9af05fad70722aa2bba7da94f9d72168a8d925a136e846d982782cc47dd
|