Skip to main content

Tau

Distributed multi-projector rendering: state replication over UDP, OSC parameter sync, and per-projection warp/blend. For authoring multimedia work in the AlloSphere with no dependency on allolib.

In quantum physics, τ (tau) denotes the tangle, a measure of entanglement. For three or more parts it is what is left once every pairwise correlation has been accounted for: a property of the whole system, belonging to no pair within it.

The import package is tau; it is published to PyPI as tau-av.

Install

Tau is used from a clone — the examples, the tests, and the deploy scripts live in the repository tree.

git clone https://github.com/kr4g/Tau.git
cd Tau
python3 -m venv .venv
.venv/bin/python -m pip install -e .

It is also installable as a dependency in a tree of your own:

pip install tau-av

Machine self-check

.venv/bin/python -m tau.preflight

Verifies Python version, GL context, shader compilation, numba JIT, calibration presence, port availability, and UDP send/receive — run it after installing, and on any machine before it joins a cluster.

Run

The launcher lists the apps under examples/ and apps/, switches between the two, and runs the selection as a subprocess; picking another app stops the first:

.venv/bin/python -m tau.launcher        # window; --tui for a terminal menu

Further directories are listed with --apps-dir. When node agents are running (see "Running in the AlloSphere"), a launch or stop also fans out to them, so the selection changes what the whole cluster shows.

A single app is targeted directly; every app has the same entry point:

# perspective window (default view)
.venv/bin/python -m examples.<name>.app

# start in a different view: pov, cross (cubemap box), or equirect panorama
.venv/bin/python -m examples.<name>.app --view equirect

Each app adds its own flags on top of the shared renderer flags below; run it with --help, or read the module docstring in its app.py.

Controls: arrow keys look around (yaw/pitch), WASD moves in the view plane, E/C move up and down, ` (backtick) stops all motion and returns the camera to its home pose, v cycles the view (pov → cross → equirect), Esc quits. The view is local to each machine and can be changed while the app runs. A second instance started while the first is open auto-elects as a replica and syncs over the network.

The camera home pose is the origin with identity orientation; an app may capture a different one with self.nav().set_home().

Every start prints a role banner — host, role, primary/replica, broadcast target, renderer, calibration — so a process that resolved to the wrong role is visible at startup.

Renderer flags

Flag Purpose
--view {pov,cross,equirect} starting desktop view (v cycles at runtime)
--omni alias for --view cross
--sim elect this machine as the simulator (any host)
--broadcast ADDR state broadcast address override
--windowed force a windowed AlloSphere renderer (disable auto-fullscreen)
--fullscreen force a spanned undecorated window
--capture-res N per-projector capture resolution
--calibration-dir DIR calibration directory (<host>.txt + projN.bin)
--no-gui suppress the control panel

Environment

Variable Effect
TAU_PRIMARY_HOST hostname that elects as primary (default ar01)
TAU_NO_GUI=1 never open the control panel
TAU_NO_NUMBA=1 force the numpy path even where Numba is installed
TAU_PARALLEL_MIN population below which the parallel neighbor kernel runs serially (default 1500); thread spin-up costs more than it saves for small counts
TAU_CACHE_DIR where precomputed data is cached; point it at a shared path so every node loads one copy (default: XDG user cache)

Writing an app

Apps you write go in apps/. An app is a Python module that subclasses DistributedApp and overrides a few methods: on_init, on_create, on_animate(dt), on_draw(g), and optionally on_gui(panel) and on_keys(keys). The same file runs as a window on one machine and across the cluster in the AlloSphere, where the runtime elects a primary, replicates state to the renderers, and warps and blends each projector from its calibration.

The apps under examples/ all follow one layout: a model module holding the algorithm as vectorized numpy, a state.py declaring the replicated dtype, and an app.py with a main() that calls tau.run.

on_animate(dt) runs once per frame; on_draw(g) runs once per projector per eye. Build and upload geometry in on_animate, and issue only draw calls in on_draw. An app that uploads inside on_draw renders correctly in a window and differently on each projector.

Where your code goes

tau/ and examples/ change upstream. Two directories are yours:

Directory Contents
apps/ apps you write; the launcher switches between these and the examples
ext/ code your apps import: helpers, kernels, shaders

Both ship empty and their contents are ignored by git, so a pull does not affect them. An app in apps/<name>/ runs as python -m apps.<name>.app, the same shape as an example; anything under ext/ is imported directly, as from ext.<module> import .... Nothing under ext/ is a launch target — the node agent runs modules from apps., examples., and tau. only.

Working with a coding agent

AGENTS.md carries the conventions and the reasons for them, in a form meant to be read by an agent as much as by a person; agents working in a clone pick it up from the repository root without being asked. The apps under examples/ are the patterns to work from.

The checks below cover what can be checked automatically. Whether an app reads from inside the AlloSphere is not one of those things — it can pass everything and still be composed for a rectangle. Look at it in --view equirect and --view pov.

Control panel

A second window with a view selector, a slider or field for every registered parameter, and the cluster roster. Apps add custom UI by overriding on_gui(panel).

It opens only on the simulator/primary; render nodes never open one. Disable it with --no-gui or TAU_NO_GUI=1.

Shaders

The renderer supplies tau_ModelViewMatrix, tau_ProjectionMatrix, and tau_ViewMatrix. Declare whichever the shader uses:

uniform mat4 tau_ModelViewMatrix;
uniform mat4 tau_ProjectionMatrix;

Shaders loaded through ShaderManager reload on file change while the app runs.

Checking an app

The suite is layered so that a pass on one machine predicts behavior on the cluster. Every app is drawn twice for the same frame through the multi-projector path and must produce identical output. Every shader must compile at #version 410, the strictest version the renderers accept. The warp composite is checked pixel-for-pixel against an independent reimplementation, and a two-process rehearsal runs election and transport over loopback.

.venv/bin/python -m pytest

bash scripts/test-py310.sh runs the same suite on the interpreter the renderers use. Broadcast delivery on a subnet, driver differences, the spanned X screen, and quad-buffer stereo are checked on site.

For cost rather than correctness, python -m tests.bench_sphere reports simulation and render timings; --save before.json and --compare before.json bracket a change. Set TAU_CALIBRATION_DIR to profile against a real calibration set.

Running in the AlloSphere

Stage the app on the shared /alloshare mount and build the venv there once, from a renderer (Linux/x86_64): bash deploy/build_venv.sh. Then either start the same app on every machine by hand:

# identical on the simulator and on every renderer
# (e.g. broadcast to all panes in an iTerm2 multishell)
.venv/bin/python -m examples.<name>.app

or start the node agents once and switch content from the simulator alone:

bash deploy/launch_sphere.sh start      # an agent on every renderer
.venv/bin/python -m tau.launcher        # pick an app; the cluster follows

Role and renderer are auto-resolved by hostname and calibration, so no flags are needed. The rank-0 host is the primary and sends state; the renderers are replicas that receive it. A renderer with a /home/sphere/calibration-current/<host>.txt manifest applies warp and blend and runs fullscreen automatically. To drive the cluster from a machine whose hostname the cluster does not know, add --sim.

State ships as full snapshots fragmented over UDP, latest-wins, with 16 MB socket buffers on both ends.

Cluster status

Every node broadcasts a heartbeat once a second. The primary's control panel shows the roster (host, role, app, frame rate), and

.venv/bin/python -m tau.heartbeat

is the same table in a terminal. Two simultaneous primaries — for example --sim on a laptop while the resident simulator is up — are reported on both.

Projector identification

Setting the /tau/pattern parameter (a slider in every app's control panel; number keys 05 in examples.calibration) switches all renderers into a diagnostic pattern without stopping content: per-projector labels, solid hash colors, viewport outlines, checkerboards, or an orientation glyph that distinguishes a physically rotated projector from bad warp data. 0 returns to normal rendering. Degraded states — no calibration, state not arriving — are drawn on the output itself.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tau_av-0.1.1.tar.gz (274.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tau_av-0.1.1-py3-none-any.whl (118.1 kB view details)

Uploaded Python 3

File details

Details for the file tau_av-0.1.1.tar.gz.

File metadata

  • Download URL: tau_av-0.1.1.tar.gz
  • Upload date:
  • Size: 274.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for tau_av-0.1.1.tar.gz
Algorithm Hash digest
SHA256 fdc3ac5e3ba1d99c14e567998b92a40ef0901ff536ce359ca1334a4cc1821214
MD5 3f3ee8f3b40820ed10439a03e0ceb36d
BLAKE2b-256 8898ee2c1adc7ff9b492cc92658a52a73498b10e7268ccfb954c0be9308d0cc9

See more details on using hashes here.

File details

Details for the file tau_av-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: tau_av-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 118.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for tau_av-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f69db7dbcd721efab686fc51c6925ba4f317db31a4496a46bdbeb045f34b8eea
MD5 b64abe2d2915d4650a4185f524dda8c4
BLAKE2b-256 216733dc796a22420ac157ccbbab2538ef087be5d64ae0c2e239add390793749

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page