CaltechExperimentalGravity / CaltechExperimentalGravity/system_ident
Stage C: CDSTransport seam + AWGNDSTransport (awg/cdsutils/gpstime)
- Dominant language
- Python
- Stars
- 0
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
**Stage C (spec §4.1).** The pluggable transport
[the roadmap already asks for](https://github.com/CaltechExperimentalGravity/system_ident/blob/feat/cds-hardware-backend/notes/40m-sos-campaign-handoff-2026-07.md) ("behind a **pluggable
transport**"), and what makes the backend and safety work verifiable without hardware.
New `src/system_ident/backends/cds_transport.py`:
```python
class CDSTransport(Protocol):
def now_gps(self) -> float: ...
def probe_rate(self, channels) -> float: ... # getdata(chans, 1)
def start(self, channel, array, rate, start_gps, ramptime): ... # -> handle
def stop(self, handle, ramptime) -> None: ...
def fetch(self, channels, duration) -> dict[str, Capture]: ... # data, start_gps, rate
```
`AWGNDSTransport` ports the sibling project's `measurement/backend_rtcds.py` (branch `40m-sys-test`),
**comments included** — the comments are the hardware lessons:
1. **The `Thread.isAlive` shim.** python-awg 3.1.2 calls `Thread.isAlive()` at `awg.py:706`, removed in
Python 3.9, so `ArbitraryLoop.start()` dies on its first line and **every injection fails before it
begins**. The site CDS stack runs awg under Python 2.7, so this only appears in a pinned py3.9 conda
env. Patch the class at import, not site-packages — an env rebuild would discard the latter.
2. **The `started`-flag `finally` stop**, verbatim: always stop the excitation, but only if it actually
started (`ArbitraryLoop.stop()` joins its worker thread and raises "cannot join thread before it is
started" otherwise, **masking the real error**); print a loud warning on a failed stop; re-raise only
when nothing else is already propagating.
3. **Probe the rate, don't configure it** — a one-second read-back, and **print it with its source
channels**. A Foton-derived seed model assumes a front-end rate, and a mismatch silently invalidates
the whole run.
4. **Lazy import** of `awg`/`cdsutils`/`gpstime` inside `AWGNDSTransport.__init__`, never at module
scope, so `import system_ident` stays clean on a plain scientific stack — the contract
[`src/system_ident/backends/cds.py:3`](https://github.com/CaltechExperimentalGravity/system_ident/blob/feat/cds-hardware-backend/src/system_ident/backends/cds.py#L3) already states.
5. **Site environment precondition.** `cdsutils/nds.py` reads the site IFO variable at *import* time and
raises `NDSError: IFO environment variable not specified` otherwise — check it first and raise
actionably. Its **value is site configuration, not a constant** (it is `C1` at the 40m); that belongs
in the deferred site-profile layer, never hardcoded. Also document the trap: sourcing the site
workstation rc script prepends the Python 2.7 CDS stack to `PYTHONPATH`, after which `import
cdsutils` dies with `ModuleNotFoundError: No module named 'matrix'`; unsetting `PYTHONPATH` recovers.
### Acceptance
`tests/test_cds_lazy_import.py` — `import system_ident` must not import `awg`/`cdsutils`. Transport unit
tests on the Stage A fakes.
---
**Campaign:** CDS hardware backend · branch [`feat/cds-hardware-backend`](https://github.com/CaltechExperimentalGravity/system_ident/tree/feat/cds-hardware-backend)
· [spec](https://github.com/CaltechExperimentalGravity/system_ident/blob/feat/cds-hardware-backend/docs/superpowers/specs/2026-08-03-cds-hardware-backend-design.md) · [plan](https://github.com/CaltechExperimentalGravity/system_ident/blob/feat/cds-hardware-backend/docs/superpowers/plans/2026-08-03-cds-hardware-backend.md) · [handoff](https://github.com/CaltechExperimentalGravity/system_ident/blob/feat/cds-hardware-backend/notes/cds-hardware-bringup-2026-08.md)
*Code is deferred until the plan and issues have been reviewed.*
Contributor guide
No contributing guide indexed for this repository
Research direction
Read the transport contract in the issue, the import boundary at src/system_ident/backends/cds.py:3, and the referenced Stage A fakes and sibling measurement/backend_rtcds.py. Start with tests/test_cds_lazy_import.py and the plan/spec; done means lazy imports remain clean and transport unit tests cover the stated behavior without requiring hardware.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100