# Getting started

Run OBS in its normal visible console. Run student Python in another terminal or
notebook on the same computer. The existing local console must be enabled; its
default port is 8221. Equipment access uses the existing local operator privilege.
No Hub account login or Hub connection is used for student communication. OBS's
existing startup, weather/enclosure, and other online dependencies still apply.

The control client requires Python 3.10 or later and uses the standard library.
The optional image measurement methods use NumPy and `astropy.io.fits` in the
student's Python environment. Reading compressed pipeline source catalogues also
uses `zstandard`. These imports occur only when the corresponding method is called;
OBS's interpreter or Nuitka executable remains independent.

From the source repository root:

```powershell
python -m nextastro_obs_client.examples.inspect_observatory
python -m nextastro_obs_client.examples.single_exposure --ra 12.5 --dec -30 --target "Student field" --filter V --seconds 5
```

For a script stored elsewhere, use the source runner directly:

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

For a compiled distribution, use its isolated `student_python` directory:

```powershell
python C:\path\to\obs.dist\student_python\nextastro_obs_client\run_script.py C:\students\my_script.py
```

Keep actively developed code in its owning checkout; the
build stages this directory for distribution with the actual executable.

In a notebook, add the parent of the client directory to the notebook kernel's
import path once:

```python
import sys
sys.path.insert(0, r"C:\path\to\codexobs")  # compiled: C:\path\to\obs.dist\student_python
from nextastro_obs_client import Observatory

obs = Observatory()  # use port=... if the local console has a different port
print(obs.site)
print(obs.status())

with obs.session(name="Notebook experiment", userid="student01"):
    images = obs.camera.expose(seconds=5, filter="V", count=1)
    print(images.paths)
```

`Observatory()` reads capabilities. Entering `obs.session(...)` performs the
controlling connection: it blocks until handover is complete. Reading status
does not acquire equipment. Keep a context open across the notebook work that
needs coherent control; exiting it relinquishes script ownership.

The supplied rotator-flat example performs real acquisitions when run against
a real OBS. Edit temperatures, exposure times, and filter names for that camera.
Mechanical rotation is the controller's mechanical frame. Do not transfer old
MaxIm/ASCOM sky-angle zero offsets into this frame without interpreting them.

See the [example library](examples/README.md) for experiments, command lines,
scientific assumptions, and suggested extensions. Every example also accepts
`--help` without connecting to OBS.
