Metadata-Version: 2.5
Name: plesty-pol-pl
Version: 0.2.0.dev1
Summary: Polarization-dependent photoluminescence of quantum dots, with fine-structure analysis.
Author-email: Yunshuang Yuan <yunshuang.yuan@fkp.uni-hannover.de>
Maintainer-email: Plesty Development Team <plesty.dev@example.com>
License-Expression: LGPL-3.0-or-later
License-File: LICENSE
License-File: LICENSES/LGPL-3.0-or-later.txt
Requires-Python: >=3.12
Requires-Dist: plesty-fss>=0.1.0
Requires-Dist: plesty-lib[fit]>=0.6.0
Provides-Extra: gui
Requires-Dist: plesty-lib[gui]>=0.6.0; extra == 'gui'
Description-Content-Type: text/markdown

# Plesty Polarization-dependent PL

Polarization-dependent photoluminescence of quantum dots. A half-wave plate on a
Thorlabs K10CR1 rotation stage sits in the detection path in front of a fixed
polarizer. For every plate angle the experiment takes one spectrum; after the
last angle of a dot it runs the `FineStructure` analyzer from
[plesty-fss](https://gitlab.com/plesty/hub/analyzers/plesty-fss) over that dot's
spectra and saves the fine-structure splitting of every emission line in the run.

## How it is built

`rig.py` connects the two device servers — the K10CR1 stage (`hwp`) and the
LightField spectrometer (`spec`) — into one `CompositeDevice` and owns the whole
device vocabulary: home and move the plate, set up and take a spectrum.
`experiment.py` turns the configuration into a fixed plan (one step per dot per
angle, then one analysis step per dot), runs it step by step and commits one
record per step to `<run_root>/<run_id>/records.jsonl`, which is what makes a run
resumable. Spectra never cross the network: the spectrometer host writes them to
the shared disk and only their paths travel.

## Installation

```bash
git clone https://gitlab.com/plesty/hub/experiments/plesty-pol-pl.git
cd plesty-pol-pl
uv sync
```

The stage and spectrometer servers are installed and run from their own
repositories, on the computers the hardware is attached to.

## Running it without a lab

The easy way is the Bench app's welcome (*Help ▸ Welcome…* ▸ *Install the
demo*). By hand — the commands and why each is needed are in the
[documentation](docs/running.md#running-it-without-a-lab):

```bash
cp setup.yaml /tmp/pol-pl-fleet.yaml
LOCAL_DATA=/tmp DEVICE_DATA_ROOT=/tmp DEVICE_DATA_PATH=/tmp \
  plesty-server -f /tmp/pol-pl-fleet.yaml fleet up
plesty-server -f /tmp/pol-pl-fleet.yaml fleet status   # the two ports
HWP_ADDRESS=tcp://localhost:<hwp port> SPEC_ADDRESS=tcp://localhost:<spec port> \
  PLESTY_DATA=/tmp uv run python -m plesty.pol_pl --config config/demo.yaml
```

`setup.yaml` brings up the stage under `--mock` and the spectrometer's replay
server, both on this machine (the bench `bench-local`); the demo writes its
spectra under `/tmp`. Under the bench, the bench gives each device its folder
and the run the devices' addresses and the shared-disk path; installing the
module writes the `.env`, and *Configure… ▸ Device Setup* edits it and
`setup.yaml` together.

That is a real run of this experiment: the same plan, the same records, the
same analysis, resumable the same way. Nothing in this module knows it is a
demo, because nothing here is different — the setup is. The stage is the
released module under `--mock`, and the spectrometer is the `demo/pol-pl`
branch of `plesty-lightfield-spectrometer`, which hands back spectra really
measured on sample E098-SIL (QD-001, QD-002 or QD-003, 0–178° in 2° steps).

An acquisition says nothing about where the run has got to, so that server
reads the run's `journal.jsonl` and answers for the step it finds there. Set
the dot in `config/demo.yaml`; a sweep the recording does not hold is refused
rather than answered with another spectrum.

## Running the experiment

Run it from the Bench app, which serves both devices on this machine's bench
and gives the run their addresses. By hand, copy `.env.example` to `.env` and
set the two device addresses and `PLESTY_DATA`, where this machine sees the
shared data disk: runs go to `<PLESTY_DATA>/pol-pl/<run_id>` and spectra to
each run's `raw/spec`. Tune the measurement in `config/default.yaml`.

```bash
# Preview the plan without touching devices
uv run python -m plesty.pol_pl --dry-run

# Run
uv run python -m plesty.pol_pl --config config/default.yaml

# Resume an interrupted run
uv run python -m plesty.pol_pl --resume <run_id>

# What this module takes — run command, environment, configuration schema
uv run python -m plesty.pol_pl --manifest
```

A started run is paused, resumed, cancelled or aborted through
`plesty.lib.experiment.control` on its run directory — see the
[documentation](docs/index.md).

## Results

- Each spectrum's record: dot, commanded and reported plate angle (`hwp_deg`,
  `hwp_reported_deg`), the spectrum file, exposure window and grating centre.
- Each dot's analysis record: for every emission line its position, the
  fine-structure splitting ± σ in µeV, whether that splitting is valid, and the
  polarization axis, plus any analyzer warnings.
- The full analyzer outputs under `<run_dir>/analysis/`:
  `<dot>_fine_structure` and `<dot>_line_fit`, and the analyzer's report of
  them, `<dot>.report.json` — a sentence, a table of the lines and the sweep
  drawn, ready to render as HTML or LaTeX.

The splitting is read from how far a line's fitted position oscillates with the
plate angle. That measures a doublet only while its two components are closer
than the linewidth and appear as one line; lines where that does not hold are
marked `fss_valid: false` and named in the warnings.
