# Configuration Everything an operator tunes lives in the measurement config (`config/*.yaml`, frozen into the plan — a resumed run refuses a changed configuration). ## Per-experiment parameters | Key | Default | Adapt when | |---|---|---| | `sample` | `"sample-000"` | Always — recorded in every row record, and the first part of each frame's name. | | `qds` | one dot at (0, 0) | One entry per quantum dot to sweep: `id`, `x_um`, `y_um` (chip frame; recorded for the future positioning stage — the steps assume the dot is already localized). The `id` is the second part of each frame's name. | | `hwp.start_deg` / `stop_deg` / `step_deg` | 0 / 90 / 2 | The angle series, endpoints inclusive. The plate angle sets the excitation power: HWP 0–90° takes it through one full period; 0–180° covers two for symmetry checks. Finer `step_deg` = more rows. | | `spectrum.exposure_s` | 1.0 | Per-row exposure in seconds, set by signal strength. A list such as `[0.5, 1.0]` takes one spectrum per exposure at every angle, in the order listed. | | `spectrum.frames` | 1 | Frames stored per acquisition (the row is frame 0). | | `powermeter.wavelength_nm` | 780 | The excitation laser's wavelength, not the emission's (powermeter correction curve). | | `powermeter.averaging` | 10 | Samples per power reading (~3 ms each), taken inside the exposure window. | | `powermeter.delay_s` | 0.4 | Delay before the power sample so it lands inside the exposure (LightField opens the shutter ~0.3–0.5 s after the call). | | *(whole `powermeter` block)* | present | **Delete it for a spectra-only sweep** — no `PM_ADDRESS`, no powermeter server, no power keys in the records. | | `analysis.enabled` | true | Analyse each dot's power series after the sweep (needs the `powermeter` block): the integrated counts and every fitted line against the power, each with a power law $I \propto P^k$; results and report under the run's `analysis/`. | | `analysis.region_nm` | null | `[start, stop]` holding the dot's lines — integrated, and where lines are fitted. Set it when the window also shows substrate or neighbouring dots. | | `analysis.background_nm` | null | `[start, stop]` free of emission, for each frame's background and noise; null takes the frame's median. | | `analysis.snr` | 5.0 | A point enters a power-law fit only this many noise σ above zero. | | `analysis.fit_options` | {} | Passed to `plesty.lib.analyzer.SpectrumFit` over the defaults (`prominence` 40 counts, Gaussian lines, constant background, FWHM bounded to 0.03–0.3 nm), e.g. `peaks: [787.7, 789.3]`. | | `step_settle_s` | 0.3 | Pause after each completed row — breathing room for the instrument stacks. | | `max_retries` / `retry_sleep` | 2 / 3.0 | Per-step retry policy for transient failures. | ## Spectra-only sweeps Delete (or comment out) the `powermeter` block. The plan then contains rotate-and-expose rows only, the rig is built without the powermeter, and the records carry no power keys. A plan that promises power readings refuses to run on a rig without a powermeter rather than producing rows without the reference. A worked example ships with the module: `config/fullrotation-spectra.yaml`, the configuration of the first successful spectra-only full rotation (2026-08-14) — run it as `uv run python -m plesty.pow_pl --config config/fullrotation-spectra.yaml`. ## What is *not* per-experiment The packaged `plesty/pow_pl/config.yaml` holds hardware constants — which sub-devices the rig is made of and their operation budgets (move/home timeouts, acquire grace). Those are properties of the instruments, and changing them belongs in a commit, not in a run config.