Metadata-Version: 2.5
Name: plesty-perovskite-g2-search
Version: 0.1.1
Summary: Map a sample cell by cell and measure g2(0) at every bright point as the scan passes, with the emitters' saturation curves.
Author-email: Yunshuang Yuan <yunshuang.yuan@fkp.uni-hannover.de>
Maintainer-email: Plesty Development Team <yunshuang.yuan@fkp.uni-hannover.de>
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-lib[fit]<1,>=0.6.1
Provides-Extra: gui
Requires-Dist: plesty-lib[gui]<1,>=0.6.1; extra == 'gui'
Description-Content-Type: text/markdown

# Plesty Perovskite G2 Search

Search a sample for single-photon emitters and measure the saturation curve of
each one found. With the laser on at the search power, the stage maps the
count rate in fine steps (0.1 µm), row by row in +x. A bright point is judged
where the stage is, the moment it is read, and the row goes on from it: the
stage never moves back. A spot is kept only if two conditions hold:

1. its count rate is well above the background mapped so far, and
2. the second-order correlation at zero delay, **g2(0)**, is below 0.5 — the
   mark of a single-photon emitter (a source that rarely emits two photons at
   once) — from enough coincidences to tell.

A spot failing either condition is recorded and the map goes on. An emitter
gets a saturation curve: its count rate at each laser power of a series, read
against a powermeter.

```text
laser on (8 %) -> map the area cell by cell (2 um cells), each cell in
                  0.1 um steps, each row in +x; at each point:
      -> (1) a spot? 3 x the background so far, >= 150 kcps, still climbing
      -> there and then, the stage still: g2, 20 s: g2(0) < 0.5?  no -> row on
                                          -> saturation curve, then row on
```

## The rig

| Sub-device | Instrument | Server on the bench (`setup.yaml`) |
|---|---|---|
| `stage` | Thorlabs KST201 x/y/z stage (ZST225 actuators); only x and y move | `kst201-d2xx`, `plesty-kst201` |
| `tt` | Swabian Time Tagger, the two detectors of a Hanbury Brown–Twiss setup | `swabian-tt`, `plesty-swabian-tt` |
| `laser` | PicoQuant Taiko PDL M1 | `taiko-pdl-m1`, `plesty-taiko-pdl-m1` |
| `pm` | Thorlabs PM-series powermeter (PM100D), optional | `pow`, `plesty-thorlabs-powermeter` |

`setup.yaml` declares the servers as the perovskite bench does, names and
sources alike; the bench starts each and gives the run its address
(`KST201_D2XX_ADDRESS`, `SWABIAN_TT_ADDRESS`, `TAIKO_PDL_M1_ADDRESS`,
`POW_ADDRESS`), which the rig's sub-devices read.

## Choices in `config/default.yaml`

- **`laser.mode`** — `pulsed`: g2(0) is the area of the zero-delay peak over
  the mean area of the side peaks, which sit at multiples of the laser period.
  `cw`: g2(0) is the coincidences around zero delay over the histogram's far
  wings.
- **`map`** — the area in stage mm, its cells (`cell_um`) and its step. Cells
  are mapped one after the other, rows of cells from low y up, each in +x;
  within a cell, rows run in +x, each
  from `backlash_um` below its start, so the stepper's backlash does not shift
  sub-micron steps; a spot is judged where the row has the stage. Every move
  is checked against the map plus that approach before it is sent.
- **`candidates`** — the background is a low percentile of the points mapped
  so far; a spot reads `contrast` times it and above `min_cps`, still climbing
  its patch, and a patch is judged again `rejudge_gain` times brighter.
- **`g2.permille`**, **`g2.min_coincidences`** — the g2's own laser power
  (lower than the map's keeps biexciton emission out of the dip), and the
  coincidences below which a g2 is inconclusive rather than a verdict.
- **`saturation`** — the powers from `start_permille` to `stop_permille` in
  `points` steps, `log` or `linear`.
- **`powermeter`** — delete the block to run without one; the saturation
  curve's power axis is then the laser's own calibrated estimate.

The saturation curve is fitted with `I(P) = I_inf · P / (P + P_sat) + b · P`,
the linear term taking the background that grows with the power.

## Running

```bash
uv sync
uv run python -m plesty.perovskite_g2_search --dry-run          # the plan, no devices
uv run python -m plesty.perovskite_g2_search                    # config/default.yaml
uv run python -m plesty.perovskite_g2_search --resume <run_id>  # continue a run
```

Copy `.env.example` to `.env` first and fill in the bench's address, token and
data paths. Runs land in `<PLESTY_DATA>/perovskite-g2-search/<run_id>`, one
record per step in `records.jsonl`: each map row, the candidates, and per
candidate where it was aimed, its correlation, g2(0) and verdict, and for an
emitter its saturation points and fit. An interrupted run resumes at the step
it stopped at; the laser is turned off however a run ends.
