plesty.pow_pl

Power-dependent PL experiment module.

Submodules

Attributes

PlestyPowPlExperiment

Classes

Experiment

Measure the power-dependent spectral series of every catalogued QD.

Functions

load_config(→ dict[str, Any])

Load the packaged module configuration (constants and running defaults).

Package Contents

class plesty.pow_pl.Experiment(devices: plesty.pow_pl.rig.PowPlRig | None = None, config: dict[str, Any] | None = None, run_root: str | pathlib.Path | None = None, **kwargs: Any)

Bases: plesty.lib.experiment.Experiment

Measure the power-dependent spectral series of every catalogued QD.

Configuration comes from a plain dict (loaded from config/*.yaml by __main__) and is frozen into the plan, so a resumed run refuses a changed configuration. Instruments are accessed exclusively through the PowPlRig composite passed at construction.

Initialize the experiment.

Parameters:
  • devices (Optional[plesty.pow_pl.rig.PowPlRig]) – The instrument rig (HWP stage, spectrometer, powermeter); may be None for plan-only inspection.

  • config (Optional[dict[str, Any]]) – Measurement configuration (see config/default.yaml); recorded in the plan.

  • run_root (str | pathlib.Path | None) – Directory under which each run creates its data directory — RUN_ROOT under PLESTY_DATA for a run started by the command line.

  • **kwargs (Any) – Forwarded to the base Experiment (name, max_retries, retry_sleep, data_root).

rig = None
config
_announced_qd: str | None = None
_configured: tuple | None = None
_grating_center_nm: float | None = None
_rows_done = 0
_rows_total = 0
build_plan() → plesty.lib.experiment.Plan

Expand the configuration into one atomic step per QD per HWP angle.

Each step commands one absolute angle (absolute targets, so no drift accumulates over the series) and one simultaneous spectrometer + powermeter acquisition; resume granularity is the single angle. With a list of exposures, every angle gets one step per exposure, in the order listed, before the plate moves on.

Returns:

The frozen measurement schedule; step ids look like qd[QD-01]-hwp[004.00], or qd[QD-01]-hwp[004.00]-exp[0.500s] with several exposures.

Raises:
  • KeyError – If a catalogue entry has no id.

  • ValueError – If the HWP sweep configuration is invalid.

Return type:

plesty.lib.experiment.Plan

record_rig() → dict[str, Any]

Record the instrument identities for replayability.

Returns:

Each device’s identity string (model, serial, firmware) and the UTC time it was recorded.

Raises:

RuntimeError – If the experiment was constructed without a rig.

Return type:

dict[str, Any]

measure_row(sample: str, qd: str, x_um: float, y_um: float, angle_deg: float, exposure_s: float, frames: int, pm_wavelength_nm: float | None = None, pm_averaging: int | None = None, pm_delay_s: float = 0.4, settle_s: float = 0.0) → dict[str, Any]

Rotate the HWP to one angle, then acquire the row.

With powermeter parameters (a plan from a config with a powermeter block) the spectrum and the power are acquired together; without them the row is the spectrum alone. Settings are pushed to the instruments once per process — on the first row, or whenever a step carries different values — so a resumed run configures itself without rewriting identical settings on every row.

Parameters:
  • sample (str) – Sample identifier, recorded in the result.

  • qd (str) – Quantum-dot identifier from the catalogue.

  • x_um (float) – Catalogued chip-frame X coordinate in micrometres.

  • y_um (float) – Catalogued chip-frame Y coordinate in micrometres.

  • angle_deg (float) – Commanded absolute HWP angle in degrees.

  • exposure_s (float) – Spectrometer exposure in seconds.

  • frames (int) – Frames stored per acquisition (row is frame 0).

  • pm_wavelength_nm (Optional[float]) – Powermeter correction wavelength in nanometres (written once per configure); None measures the spectrum without a power reference.

  • pm_averaging (Optional[int]) – Powermeter samples per reading (~3 ms each).

  • pm_delay_s (float) – Delay before the power sample so it lands inside the exposure window.

  • settle_s (float) – Pause after the completed step — breathing room for the instrument stacks between rows (defaults to 0 for plans frozen before the knob existed).

Returns:

identifiers, coordinates, commanded and reported HWP angle, the shared-disk path of the saved frame, the grating center wavelength, and — when measured — the simultaneous optical power.

Return type:

A JSON-serializable record

Raises:

RuntimeError – If the experiment was constructed without a rig, or if the plan carries power parameters but the rig has no powermeter.

analyze_qd(qd: str) → dict[str, Any]

Analyse one dot’s power series and save the results beside the run.

Reads the dot’s spectra back from this run’s records, then the two analyses of analysis: the integrated counts and every line’s fitted area against the power. The line fit is saved as analysis/<qd>_line_fit and the report as analysis/<qd>.report.json, which the bench’s run report shows without importing this module.

Parameters:

qd (str) – Quantum-dot identifier.

Returns:

Each line’s position and exponent, the integrated exponent, the saturation power when the data constrain it, the line fit’s warnings, and where the results were saved.

Raises:

RuntimeError – If the run has not started.

Return type:

dict[str, Any]

_grating_center() → float | None

Return the grating center wavelength, queried once per process.

The spectrometer’s LightField IPC link is the fragile part of the rig — static settings are read (and written) once, not per row. A value the spectrometer cannot report (empty or non-numeric) is recorded as None with one warning; metadata must not abort a sweep whose frames and power are fine.

Return type:

Optional[float]

_ensure_at_qd(qd: str, x_um: float, y_um: float) → None

Positioning placeholder — the dot is assumed to be localized.

Logs once per dot, not per angle. The upcoming localization stage will move the AMC300 to the catalogue coordinates, verify via the DMK camera, and fine-steer the PI mirror before the sweep starts.

Parameters:
  • qd (str)

  • x_um (float)

  • y_um (float)

Return type:

None

async setup() → None

Connect the instruments, route the frames into raw/spec, home the wave plate.

The frame directory is set through the device’s own data path rather than by writing a vendor parameter: the spectrometer resolves it under its bench’s folder on the Plesty share, creates it, and answers with that folder from the share, where each frame is recorded (route()). Only the spectrometer is routed — the stage and the powermeter write nothing.

Raises:

RuntimeError – If this machine is not told where the Plesty share is, so it could not read the frames back.

Return type:

None

async teardown() → None

Park the wave plate at 0 deg (best effort), then disconnect.

Return type:

None

plesty.pow_pl.PlestyPowPlExperiment
plesty.pow_pl.load_config() → dict[str, Any]

Load the packaged module configuration (constants and running defaults).

Returns:

The parsed config.yaml shipped with this module.

Return type:

dict[str, Any]