Skip to content

Commit 95cbcf4

Browse files
committed
Add CLAUDE.md with repo guidance
Add CLAUDE.md to provide guidance for Claude Code and contributors. The file documents project identity (MeasureIt/qmeasure), build & development commands, testing conventions, architecture (sweep hierarchy, concurrency guard, threading model, package layout), data directory behavior, sweep timing constraints, code style, and known issues. Intended to help code-assistants and developers understand how to run, test, and extend the project.
1 parent 1d67758 commit 95cbcf4

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

CLAUDE.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Identity
6+
7+
MeasureIt is a QCoDeS-based measurement software for condensed matter physics experiments. It is published on PyPI as `qmeasure` but imported as `measureit`. The repository name is `MeasureIt`.
8+
9+
## Build & Development Commands
10+
11+
```bash
12+
# Install (editable with all dev deps)
13+
pip install -e ".[dev,docs,jupyter]"
14+
15+
# Run all tests with coverage
16+
pytest
17+
18+
# Run specific test categories
19+
pytest tests/unit -v
20+
pytest tests/integration -v
21+
pytest tests/e2e -v
22+
pytest -m "not slow"
23+
24+
# Run a single test file
25+
pytest tests/unit/test_sweep1d.py -v
26+
27+
# Lint and format
28+
make format # ruff format + ruff check --fix
29+
make lint # ruff format --check + ruff check + mypy
30+
31+
# Build docs
32+
make docs # outputs to docs/source/_build/html/
33+
```
34+
35+
Tests use `QT_QPA_PLATFORM=offscreen` (set in `tests/conftest.py`). Qt/pytest-qt integration tests are skipped in CI but should be run locally. Each test gets an isolated `MEASUREIT_HOME` via the `temp_measureit_home` fixture.
36+
37+
## Architecture
38+
39+
### Sweep Hierarchy
40+
41+
`BaseSweep` (in `src/measureit/sweep/base_sweep.py`) is the central class. It owns:
42+
- A `RunnerThread` (QThread in `_internal/runner_thread.py`) for data acquisition
43+
- A `Plotter` (QObject in `_internal/plotter_thread.py`) for real-time visualization
44+
- `ProgressState` / `SweepState` for status tracking
45+
- Parameter following, QCoDeS `Measurement` creation, and save/plot lifecycle
46+
47+
Concrete sweep types: `Sweep0D` (time-based), `Sweep1D` (single param), `Sweep2D` (dual param, composes an inner `Sweep1D`), `SimulSweep`, `SweepIPS`, `GateLeakage`, `Sweep1D_listening`.
48+
49+
### Concurrency Guard
50+
51+
A module-level `WeakSet` (`_ACTIVE_SWEEPS`) enforces that only one non-queued sweep runs at a time. Inner sweeps and sweeps sharing a parent chain are considered "related" and allowed. `SweepQueue` bypasses this guard. `start_force()` kills unrelated active sweeps before starting.
52+
53+
### Threading Model
54+
55+
All threading uses PyQt5 `QThread` + signals/slots, **not** Python `threading.Thread`. This is required even in headless/Jupyter usage because the sweep loop (`RunnerThread.run()`) communicates data points back via `pyqtSignal`. The `conftest.py` provides a session-scoped `qapp` fixture and per-test `cleanup_qt_threads` to prevent segfaults.
56+
57+
### Package Layout
58+
59+
```
60+
src/measureit/
61+
sweep/ # Sweep classes (base_sweep, sweep0d/1d/2d, simul_sweep, etc.)
62+
_internal/ # RunnerThread, Plotter (not public API)
63+
tools/ # sweep_queue, util (init_database, safe_get/set), safe_ramp, tracking
64+
visualization/ # heatmap_thread, helper (pyqtgraph-based)
65+
legacy/ # Old matplotlib-based plotter/heatmap threads
66+
Drivers/ # QCoDeS instrument drivers for lab hardware
67+
config.py # Data directory resolution (MEASUREIT_HOME / platformdirs)
68+
logging_utils.py # Sweep file logging + Jupyter notebook log handler
69+
_deprecation.py # FutureWarning shims for old import paths
70+
```
71+
72+
Top-level shim modules (`base_sweep.py`, `sweep0d.py`, etc. at `src/measureit/`) re-export from `sweep/` with deprecation warnings. New code should import from `measureit.sweep.*` or the top-level `measureit` namespace.
73+
74+
### Data Directory
75+
76+
Priority: `set_data_dir()` > `MEASUREIT_HOME` env > legacy `MeasureItHome` env > `platformdirs` default. Subdirectories (`Databases`, `logs`, `cfg`, `Origin Files`) are created lazily on first access via `get_path()`.
77+
78+
### Sweep Timing Constraints
79+
80+
`inter_delay` minimum: 0.01s (10ms). `outer_delay` minimum: 0.1s (100ms). Values below these raise `ValueError`.
81+
82+
## Testing Conventions
83+
84+
- Mock instruments use `qcodes.parameters.Parameter` subclasses (see `conftest.py::mock_parameter`)
85+
- `fast_sweep_kwargs` fixture provides `inter_delay=0.01, save_data=False, plot_data=False, suppress_output=True`
86+
- `conftest.py` auto-clears QCoDeS instrument registry and `_ACTIVE_SWEEPS` between tests
87+
- Pandas is stubbed in `conftest.py` to avoid binary-compat issues in CI
88+
89+
## Code Style
90+
91+
- Ruff (line-length 88, Google docstrings, `py38` target)
92+
- Mypy with strict settings (configured in `pyproject.toml`)
93+
- `*_ui.py` files are auto-generated and excluded from all linting
94+
95+
## Known Issues
96+
97+
- `ipykernel` 7.0.x breaks Qt event loop; pinned to `>=6.29,!=7.*`
98+
- pytest-qt can cause macOS segfaults during teardown; `conftest.py` includes extensive guards

0 commit comments

Comments
 (0)