# Python scripting

Use `nextastro_obs_client` to control a running NextAstro OBS from a Python
script or notebook on the observatory computer. You can use loops, functions,
target lists and image measurements alongside mount, camera, filter, focuser
and rotator commands.

The client is in the **OBS checkout**, in `nextastro_obs_client/`. It talks
to OBS's local console on `127.0.0.1:8221` by default. It uses the existing local
operator access; a Hub login is not needed for this connection. Run OBS in its
normal visible console and student Python in another terminal or notebook.

## First script

Save this as `my_observation.py`. Replace the illustrative position, filter and
temperature with the ones for your observation and camera. RA is in hours,
declination in degrees, exposure time in seconds and temperature in Celsius.

```python
from nextastro_obs_client import Observatory

obs = Observatory()
print(obs.site)
print(obs.camera.status())

with obs.session(name="First Python observation", userid="student01"):
    obs.camera.cool_to(-30)
    obs.mount.slew(ra_hours=12.5, dec_deg=-30, center=True)
    images = obs.camera.expose(
        seconds=5.5, filter="V", count=3, target_name="Student field"
    )
    for image in images:
        print(image.exposure_id, image.path)
```

Run it using the client in your existing checkout:

```powershell
python C:\path\to\codexobs\nextastro_obs_client\run_script.py C:\students\my_observation.py
```

Session entry waits for current observing work to finish, then acquires script
control in manual mode. Equipment calls wait for their completion result. A
returned FITS path acknowledges the primary raw write; reduction and upload can
continue afterward. The Python API makes cooling explicit with `cool_to(...)`;
the Hub's [Linear Script](linear-scripts.md) exposure rows instead cool to the
nighttime target automatically.

## Setup and API

- [Python setup](python-scripting/getting-started.md): terminals, notebooks,
  source checkouts, compiled OBS and optional analysis dependencies.
- [Python API reference](python-scripting/api.md): all equipment operations,
  typed telemetry, native captures, results, image measurements and exceptions.
- [Handover, stopping and results](python-scripting/operation.md): ownership,
  manual mode, Ctrl+C, operator controls and saved data.
- [Protocol and compiled OBS](python-scripting/protocol-and-builds.md): local
  transport and running normal Python beside a compiled OBS executable.

## Worked examples

The [Python example library](python-scripting/examples/README.md) contains 13
examples. Each page includes the command to run it, an explanation and complete
Python source. Start with [equipment discovery](python-scripting/examples/inspect_observatory.md)
and [a first exposure](python-scripting/examples/single_exposure.md).

Examples cover colour sequences, variable-star photometry, CSV target lists,
exposure ladders, dark current, photon transfer, focus curves, adaptive flats,
dithering, video/planet/speckle and rotator calibration. Run them as modules from
the OBS checkout; the shared helpers are already there.

## Errors and interrupted work

A failed equipment operation raises `CommandFailed`. Completed images remain
available in its recorded result. `CommandCancelled` identifies cancellation.
If the connection is lost, keep the `ConnectionLost.command_id` and inspect
`obs.command_result(command_id)` before deciding what to do next: the physical
operation may already have happened. See [results and exceptions](python-scripting/api.md#results-and-exceptions).

The Python process must stay running for its live session. Ctrl+C or losing that
connection requests cancellation. A Hub linear script runs inside OBS and can
continue when its browser page closes; these are different execution models.
