{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Spectra Tune Lab light source\n", "=============================\n", "\n", "\n", "\n", "*PyPlr*'s `PupilCore().light_stamper(...)` method makes it easy to integrate any light source given a suitable geometry. For our own application, we chose to administer light stimuli with a custom-built integrating sphere and Spectra Tune Lab (STLAB: [Ledmotive Technologies, LLC](https://ledmotive.com/))—a spectrally tuneable light engine with 10 LED colour channels, capable of generating a broad range of spectral compositions. STLAB can be controlled programmatically with most languages via its *REST API*, which works with generic HTTP requests. The API includes commands to set a specific spectrum, turn the light off, get readouts from the onboard spectrometer, etc. We opted to work with STLAB because it offers a high level of control over the temporal and spectral properties of light stimuli. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*PyPlr*'s `stlab.py` module\n", "---------------------------\n", "\n", "`stlab.py` provides full native support for STLAB by encapsulating its *REST API* in a `SpectraTuneLab()` device class and streamlining various routines with helper functions. STLAB connects via ethernet to a small computer called the *Light Hub* (a BeagleBone running Linux), which in turn connects via USB to the controlling computer. When all hardware is correctly assembled and the appropriate software installed, establishing a connection to the device is easy (note that a password is required for access to the *Light Hub*): " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "STLAB device setup complete...\n" ] } ], "source": [ "from pyplr import stlab\n", "d = stlab.SpectraTuneLab(password='****************')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With this handle on the device we can access the methods available from the *REST API*. For example, to blink each of the LEDs in turn at max intensity for ~1 second, we can use the `.set_spectrum_a(...)` method:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from time import sleep\n", "\n", "for led in range(10):\n", " intensities = [0]*10\n", " intensities[led] = 4095\n", " d.set_spectrum_a(intensities)\n", " sleep(1.)\n", " d.turn_off()\n", " sleep(1.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that spectrums are defined by passing a list of ten values between 0-4095 (that's one for each LED channel, 12-bit resolution), corresponding to the minimum and maximum output of the device. \n", "\n", "STLAB also has an on-board spectrometer. The easiest way to get data from the spectrometer is with `pyplr.calibrate.SpectraTuneLabSampler`, a subclass of `SpectraTuneLab` with added sampling methods. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "STLAB device setup complete...\n", "Sampling 10 leds at the following intensities: [4095]\n", "Measurement: 1 / 10, LED: 0, intensity: 4095\n", "Measurement: 2 / 10, LED: 1, intensity: 4095\n", "Measurement: 3 / 10, LED: 2, intensity: 4095\n", "Measurement: 4 / 10, LED: 3, intensity: 4095\n", "Measurement: 5 / 10, LED: 4, intensity: 4095\n", "Measurement: 6 / 10, LED: 5, intensity: 4095\n", "Measurement: 7 / 10, LED: 6, intensity: 4095\n", "Measurement: 8 / 10, LED: 7, intensity: 4095\n", "Measurement: 9 / 10, LED: 8, intensity: 4095\n", "Measurement: 10 / 10, LED: 9, intensity: 4095\n" ] }, { "data": { "text/html": [ "
\n", " | 380 | \n", "385 | \n", "390 | \n", "395 | \n", "400 | \n", "405 | \n", "410 | \n", "415 | \n", "420 | \n", "425 | \n", "... | \n", "745 | \n", "750 | \n", "755 | \n", "760 | \n", "765 | \n", "770 | \n", "775 | \n", "780 | \n", "led | \n", "intensity | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "23.092050 | \n", "69.099876 | \n", "163.715586 | \n", "292.749028 | \n", "646.445204 | \n", "1293.727715 | \n", "2318.856104 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0 | \n", "4095 | \n", "
1 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "13.482852 | \n", "10.065324 | \n", "20.364725 | \n", "29.868263 | \n", "65.026672 | \n", "142.974411 | \n", "311.837770 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "1 | \n", "4095 | \n", "
2 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "0.000000 | \n", "1.689246 | \n", "2.240837 | \n", "3.999032 | \n", "7.308575 | \n", "15.892703 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "2 | \n", "4095 | \n", "
3 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "3.733973 | \n", "0.000000 | \n", "1.982641 | \n", "0.859144 | \n", "2.412213 | \n", "7.467946 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "3 | \n", "4095 | \n", "
4 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "0.000000 | \n", "1.434468 | \n", "0.956312 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "4 | \n", "4095 | \n", "
5 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "2.748689 | \n", "1.536901 | \n", "1.241343 | \n", "1.655125 | \n", "1.448234 | \n", "2.009794 | \n", "2.748689 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "5 | \n", "4095 | \n", "
6 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "3.008748 | \n", "0.000000 | \n", "4.851946 | \n", "9.324410 | \n", "14.420308 | \n", "14.718472 | \n", "... | \n", "50.823453 | \n", "73.700784 | \n", "55.106176 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "6 | \n", "4095 | \n", "
7 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "1.007043 | \n", "2.098007 | \n", "... | \n", "93.403277 | \n", "85.766531 | \n", "70.493039 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "7 | \n", "4095 | \n", "
8 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "8 | \n", "4095 | \n", "
9 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "... | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "9 | \n", "4095 | \n", "
10 rows × 83 columns
\n", "\n", " | time | \n", "LED-1 | \n", "LED-2 | \n", "LED-3 | \n", "LED-4 | \n", "LED-5 | \n", "LED-6 | \n", "LED-7 | \n", "LED-8 | \n", "LED-9 | \n", "LED-10 | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "4095 | \n", "
1 | \n", "2000 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "4095 | \n", "
2 | \n", "2000 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "
3 | \n", "2100 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "0 | \n", "