Skip to content

feat(spark): add spectrum scan support for absorbance and fluorescence - #1046

Merged
rickwierenga merged 2 commits into
PyLabRobot:mainfrom
xbtu2:feat/spark-spectrum-scan
May 18, 2026
Merged

feat(spark): add spectrum scan support for absorbance and fluorescence#1046
rickwierenga merged 2 commits into
PyLabRobot:mainfrom
xbtu2:feat/spark-spectrum-scan

Conversation

@xbtu2

@xbtu2 xbtu2 commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Add read_absorbance_spectrum() and read_fluorescence_spectrum() methods to ExperimentalSparkBackend, enabling wavelength-sweep spectral scanning on the Tecan Spark plate reader.

Key Design Decision

The Spark firmware natively supports wavelength range sweeps via WAVELENGTH=FROM~TO:STEP syntax in its filter commands. This implementation leverages the native sweep rather than issuing per-wavelength commands, which is both faster and simpler.

Changes

controls/optics_control.py

  • wavelength param type: Optional[int]Optional[Union[int, str]] to accept firmware range strings (e.g. '5000~5500:100')

spark_backend.py

  • Added read_absorbance_spectrum() and read_fluorescence_spectrum() public methods
  • Extracted shared helpers to reduce duplication:
    • _run_measurement(): shared background-read → scan → cleanup orchestration
    • _setup_absorbance() / _setup_fluorescence(): shared instrument configuration

spark_processor.py

  • Added process_absorbance_spectrum() and process_fluorescence_spectrum() for multi-wavelength TDCL data
  • Extracted shared helpers:
    • _find_key(): dynamic TDCL key lookup (replaces repeated next() patterns)
    • _extract_measurement_pairs(): unifies nested_mult and flat block handling
    • _extract_fluo_calibration(): shared dark/bright/K extraction
    • _reshape_to_rows(): shared wavelength→rows×cols reshaping
    • _get_dark_for_wl(): per-wavelength dark value lookup with fallback

Tests

  • 14 new tests covering spectrum scan methods and parameter validation
  • All 25 tests pass

Physical Hardware Validation

Tested on a physical Tecan Spark via USB/IP forwarding:

Scan Range Result
Absorbance spectrum 500–550nm, 10nm steps 6 wavelength points, OD ≈ 0 (empty well) ✅
Fluorescence spectrum ex 440–480nm → em 545nm 5 wavelength points, 353→213 RFU ✅

@rickwierenga

Copy link
Copy Markdown
Member

cool, thanks for the PR!

in another PR (#1033) we named the spectral scans experimental_ since we are still figuring out the PLR abstraction for those methods. This way, people can use them but it's clear that the API might change.

Add read_absorbance_spectrum() and read_fluorescence_spectrum() methods
to ExperimentalSparkBackend. These leverage the Spark firmware's native
wavelength sweep via WAVELENGTH=FROM~TO:STEP range syntax, avoiding
manual per-wavelength iteration.

Changes:
- optics_control: Accept Union[int, str] for wavelength params
- spark_backend: Add spectrum scan methods with shared orchestration
  helpers (_run_measurement, _setup_absorbance, _setup_fluorescence)
- spark_processor: Add process_absorbance_spectrum() and
  process_fluorescence_spectrum() with shared helpers (_find_key,
  _extract_measurement_pairs, _extract_fluo_calibration,
  _reshape_to_rows, _get_dark_for_wl)
- Tests: 25/25 pass, validated on physical hardware via USB/IP
@xbtu2
xbtu2 force-pushed the feat/spark-spectrum-scan branch from c12ea12 to 354de01 Compare May 18, 2026 20:34
Rename read_absorbance_spectrum -> experimental_read_absorbance_spectrum
and read_fluorescence_spectrum -> experimental_read_fluorescence_spectrum
to match the naming convention from PR PyLabRobot#1033.
@xbtu2

xbtu2 commented May 18, 2026

Copy link
Copy Markdown
Contributor Author

Good call — renamed both methods to experimental_read_absorbance_spectrum and experimental_read_fluorescence_spectrum to match the convention from #1033. Pushed in 013c8fb.

@xbtu2
xbtu2 marked this pull request as ready for review May 18, 2026 20:39
@rickwierenga
rickwierenga merged commit 71837a8 into PyLabRobot:main May 18, 2026
21 checks passed
@rickwierenga

Copy link
Copy Markdown
Member

sweeeeet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants