{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Integrating sphere\n", "==================\n", "\n", "For some experiments it may be sufficient to perform light stimulation with a standard computer monitor, but where research calls for advanced control over the geometry of retinal stimulation, a bespoke setup is required. One solution is to use a [Maxwellian view](https://medical-dictionary.thefreedictionary.com/maxwellian+view) pupillometry system, where the light stimulus is focused onto an aperture positioned in front of the eye, or in the entrance plane of a pharmacologically dilated pupil, and the consensual pupil response is measured from the other eye. But this approach requires optical engineering and resources that may not be available in the average research setting. As an alternative, we developed a low-cost integrating sphere that provides a full-field, 'Ganzfeld', stimulus and precludes the need for optical engineering, pharmacological dilation of the pupil, and strict fixation control on behalf of the participant." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Construction\n", "------------\n", "\n", "We built the sphere from two 45 cm flanged acrylic half domes ([Project Plastics Ltd](https://www.projectplastics.co.uk/)), each coated on the inside surface with [Avian-B white reflectance coating](https://aviantechnologies.com/product/avian-b-white-reflectance-coating/) to scatter light homogenously. A 28 cm opening in one of the domes serves as a viewing port and an additional 7 cm (subtending ~9 degrees from the plane of the viewing port) opening opposite the viewing port was included to allow for secondary stimuli (e.g., a fixation target) or to allow for exclusion of the foveal macular pigment from stimulation. On the same half of the sphere as the viewing port, a 30 mm entry port for the light source was cut at an angle of 22.5 deg from the top, such that it could not be seen directly when looking straight ahead. The sphere and STLAB were stabilised on a wooden fixing plate making it suitable for placement on a desk. \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calibration\n", "-----------\n", "\n", "To build a calibrated forward model of our STLAB-sphere rig that represents what an observer actually sees when looking into it, we collected measurements with an external spectrometer positioned at the plane of the viewing port. The `pyplr.calibrate` module streamlines this process with a `SpectraTuneLabSampler()` class, which is just a sub-class of `pyplr.stlab.SpectraTuneLab` with added sampling methods and support for an external spectrometer. Any spectrometer with a python interface can be integrated here with minimal effort, but we used an [Ocean Optics STS-VIS](https://www.oceaninsight.com/products/spectrometers/microspectrometer/sts-series/sts-vis/), supported by `pyplr.oceanops` and the [Seabreeze](https://pypi.org/project/seabreeze/) Python library. \n", "\n", "It would take a long time to sample every possible device setting, so we opted to sample the full range of intensities in steps of 63 for each LED. \n", "\n", "```Python\n", "from pyplr.calibrate import SpectraTuneLabSampler\n", "from pyplr.oceanops import OceanOptics\n", "\n", "oo = OceanOptics.from_first_available()\n", "d = SpectraTuneLabSampler(password='***************', external=oo)\n", "\n", "# specify leds and intensities to sample\n", "leds = [0,1,2,3,4,5,6,7,8,9]\n", "intensities = [i for i in range(0, 4096, 65)]\n", "\n", "# sample\n", "d.sample(leds=leds, \n", " intensities=intensities, \n", " external=oo,\n", " randomise=True)\n", "d.make_dfs(save_csv=True)\n", "```\n", "\n", "The above code instructs STLAB to cycle through all of the specified settings and obtain measurements with the on-board spectrometer and external spectrometer (if specified), and then finally to save the data to CSV format in the current working directory.\n", "\n", "Calibrating the resulting OceanOptics data was an involved process complicated by the need to account for the effect of spectrometer PCB temperature and integration time on the raw data. Our pipeline is shown below, minus the code for fitting the data in MATLAB. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | \n", " | 380 | \n", "381 | \n", "382 | \n", "383 | \n", "384 | \n", "385 | \n", "386 | \n", "387 | \n", "388 | \n", "389 | \n", "... | \n", "771 | \n", "772 | \n", "773 | \n", "774 | \n", "775 | \n", "776 | \n", "777 | \n", "778 | \n", "779 | \n", "780 | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
led | \n", "intensity | \n", "\n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " |
0 | \n", "0 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \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.000000e+00 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000011 | \n", "0.000000 | \n", "0.000000 | \n", "
65 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \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.000000e+00 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "|
130 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \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.000000e+00 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "0.000000 | \n", "|
195 | \n", "0.000026 | \n", "0.000017 | \n", "0.000041 | \n", "0.000015 | \n", "0.000036 | \n", "0.000039 | \n", "0.000022 | \n", "0.000032 | \n", "0.000026 | \n", "0.000021 | \n", "... | \n", "0.000022 | \n", "5.119073e-07 | \n", "0.000008 | \n", "0.000009 | \n", "0.000000 | \n", "0.000015 | \n", "0.000012 | \n", "0.000000 | \n", "0.000018 | \n", "0.000000 | \n", "|
260 | \n", "0.000141 | \n", "0.000147 | \n", "0.000168 | \n", "0.000170 | \n", "0.000155 | \n", "0.000144 | \n", "0.000154 | \n", "0.000121 | \n", "0.000167 | \n", "0.000169 | \n", "... | \n", "0.000088 | \n", "7.298278e-05 | \n", "0.000088 | \n", "0.000081 | \n", "0.000071 | \n", "0.000086 | \n", "0.000086 | \n", "0.000010 | \n", "0.000100 | \n", "0.000078 | \n", "|
... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
9 | \n", "3835 | \n", "0.003609 | \n", "0.004056 | \n", "0.003476 | \n", "0.003724 | \n", "0.002943 | \n", "0.003147 | \n", "0.003482 | \n", "0.002543 | \n", "0.003630 | \n", "0.004153 | \n", "... | \n", "0.002318 | \n", "2.590713e-03 | \n", "0.002629 | \n", "0.002536 | \n", "0.002962 | \n", "0.002583 | \n", "0.002606 | \n", "0.002213 | \n", "0.002467 | \n", "0.002924 | \n", "
3900 | \n", "0.003415 | \n", "0.003666 | \n", "0.003451 | \n", "0.003724 | \n", "0.002873 | \n", "0.003021 | \n", "0.003112 | \n", "0.002289 | \n", "0.003514 | \n", "0.004000 | \n", "... | \n", "0.002279 | \n", "2.669694e-03 | \n", "0.002370 | \n", "0.002300 | \n", "0.002815 | \n", "0.002574 | \n", "0.002412 | \n", "0.002107 | \n", "0.002590 | \n", "0.002938 | \n", "|
3965 | \n", "0.003560 | \n", "0.003867 | \n", "0.003539 | \n", "0.003874 | \n", "0.003191 | \n", "0.003165 | \n", "0.003544 | \n", "0.002428 | \n", "0.003695 | \n", "0.004005 | \n", "... | \n", "0.002134 | \n", "2.682856e-03 | \n", "0.002604 | \n", "0.002552 | \n", "0.002775 | \n", "0.002638 | \n", "0.002748 | \n", "0.002137 | \n", "0.002676 | \n", "0.002664 | \n", "|
4030 | \n", "0.003738 | \n", "0.003652 | \n", "0.003557 | \n", "0.003737 | \n", "0.002973 | \n", "0.003205 | \n", "0.003420 | \n", "0.002227 | \n", "0.003520 | \n", "0.003932 | \n", "... | \n", "0.002444 | \n", "2.647269e-03 | \n", "0.002541 | \n", "0.002408 | \n", "0.002702 | \n", "0.002547 | \n", "0.002385 | \n", "0.002038 | \n", "0.002477 | \n", "0.002837 | \n", "|
4095 | \n", "0.003459 | \n", "0.004063 | \n", "0.003610 | \n", "0.004071 | \n", "0.003099 | \n", "0.003373 | \n", "0.003231 | \n", "0.002468 | \n", "0.003654 | \n", "0.004141 | \n", "... | \n", "0.002274 | \n", "2.544598e-03 | \n", "0.002587 | \n", "0.002493 | \n", "0.002923 | \n", "0.002699 | \n", "0.002592 | \n", "0.002177 | \n", "0.002471 | \n", "0.002698 | \n", "
640 rows × 401 columns
\n", "