Skip to content

nickglazzard1959/lgscli

Repository files navigation

Little Garden Spectrometer Command Line Interface Tools

Please note: This project is specific to Linux. The spectrum capture program component is not intended to work on other operating systems, and it will not do so.

The Little Garden spectrometer is a DIY project created by Lao Kang in China. It covers the near infrared to near ultraviolet range (about 300nm to 1100nm) and has a resolution of about 1nm.



Mr. Lao offers his spectrometers for sale on Ali Express, although it isn't clear which geographic areas they can be ordered from. As I understand it, they are a spare time project for him, although he may have made a few hundred of them by now.

These devices are probably as good as a spectrometer based on a UVC video camera can be made. Mr. Lao has perfected the removal of the Bayer filter from the HD camera he uses and has also perfected the delamination of the DVDs he uses to form the grating. The "chassis" of the spectrometer is 3D printed, including the slit. Anyone who has tried to build one of these things themselves will know that it is much harder than it might seem at first (and removing the Bayer filter from a camera is very difficult -- I have never attempted that).

The software normally used with the spectrometer is the Theremino software.

The programs here are a completely different alternative. They are command line tools rather than GUI based, so they are much less "interactive". However, they try to provide everything needed to obtain fairly accurate spectra, including amplitude correction, so that the spectra can be used for colorimetric applications such as measuring colour temperature, obtaining standard colour coordinates, etc. Note that amplitude correction isn't needed for some applications, such as measuring transmission spectra or identifying emission peak wavelengths. It is essential for colour measurement applications, though.

The program that captures spectra, specap, is a C++ program specific to Linux. It has been tested on Debian 12 and an ancient version of Ubuntu (14.04). It uses Video for Linux 2 (V4L2) to access the spectrometer camera as a USB Video Class (UVC) device.

The other programs are written in Python 3 and are theoretically portable. Some of them use the Python Colour Science library and plot graphs using the GPLOT2 program.

Installation

Build and install the specap program:

./build.sh

This puts specap and specap_ancient into /usr/local/bin. The specap_ancient program is known to work on Ubuntu 14.04, but is likely of no interest. For modern Linux, use specap.

To install the Python tools, first activate a suitable venv. Then:

cd lgscli
pip install .

Capturing a spectrum

To capture a spectrum to a named file use:

specap -s result.dat

You should use the .dat extension for spectral data files.

The full set of options is described below, but the most significant parameter is exposure time, set with -e (in tenths of milliseconds). This should be set so that the acquired data peaks at 0.7 to 0.85. The default is 200 (20 ms).

For wavelength calibration, the -p option needs to be used when acquiring the spectrum of a fluorescent lamp (supplied with the spectrometer). This option writes X pixel number rather than wavelength (as this is used when the mapping of pixel number to wavelength isn't yet known).

For amplitude correction, the -n option needs to be used when acquiring the spectrum of a tungsten or tungsten halogen lamp. This option prevents any existing correction file being used.

The full set of specap options is:

-h : help
-p : select raw pixel mode for wavelength calibration.
-n : do not use amplitude correction data (use if updating correction data).
-b : bug fix for sensor/driver returning incorrect full range values.
-v : verbose informational output.
-d device (/dev/video0) : specify device name.
-f outfileName (specout.dat) : specify output file name.
-s outfileName (specout.dat) : also specify output file name.
-e exposureInt (200 (=20ms)) : specify exposure time.
-a averageFramesInt (16) : number of frames to average over.
Reads optional wavelength calibration data from /usr/local/lgscli/active_calibration.txt.
Use: wavelength_cal or wavelength_auto_cal programs to generate this from a fluorescent lamp spectrum.
Reads amplitude correction data from /usr/local/lgscli/active_correction.txt.
Use: correction_cal program to generate this from a tungsten lamp spectrum.

Wavelength calibration

There is a default wavelength calibration built in to specap, but each individual device should be calibrated so that sensor X pixel number can be accurately mapped to wavelength. A linear relationship is a very good fit and quite sufficient.

The specap program reads the wavelength calibration data from /usr/local/lgscli/active_calibration.txt if this exists. If not, it uses the built in default calibration.

Two programs can create the wavelength calibration data. One relies on reading spectral data manually and editing an input data file. The other uses peak detection. In both cases, the starting point is a spectrum of a fluorescent lamp (which contains mercury). This gives a number of sharp peaks at known wavelengths. The most prominent 8 peaks are:

404.6 nm Hg (Around pixel 300)
435.8 nm Hg (4th largest, around pixel 359)
487.7 nm Tb (Around pixel 454)
542.4 nm Tb (3rd largest, maybe. Around pixel 555)
546.1 nm Hg (Largest. maybe. Around pixel 563)
611.6 nm Eu (2nd largest, maybe. Around pixel 682)
631.1 nm Eu (Around pixel 719)
707.0 nm Eu (Around pixel 857)

The first step is to capture the spectrum of the fluorescent lamp.

specap -p -s wavecal.dat

The peaks from the lamp are very high amplitude, so it is easy to run into clipping. Aim for peak values reported by specap of around 0.85. Adjust the exposure time (-e option) if necessary.

The wavelength_auto_cal program can be used to create a calibration file from the captured spectrum using peak detection. The program attempts to find four peaks, at wavelengths 435.8, 542.4, 546.1 and 611.6 nanometers.

wavelength_auto_cal -s wavecal.dat

The output file defaults to active_calibration.txt. This will be used by specap if it is copied to /usr/local/lgscli/active_calibration.txt.

The correlation coefficient shown by the program should be at least 0.9999. If it is less than this, something has gone wrong ...

The wavelength_auto_cal program will display how well the linear function fits the pixel / wavelength data found from peak detection.



Although identifying four peaks in the spectrum automatically should work reliably, identifying all eight peaks automatically is not so easy. Humans should be able to do it, though. Using all 8 peaks should improve the accuracy of the pixel to wavelength mapping, although the automatic fit to 4 peaks is probably quite good enough.

The "manual" wavelength calibration program is wavelength_cal. The first step in using this is to have it generate a "template" specification file using:

wavelength_cal -t

which will create the file wavecal.txt (or another file name specifed with -i if desired.).

Then, examining the spectrum data file wavecal.dat in a text editor, look for each peak in wavecal.txt around the pixel position given for it in the right hand column. The actual maximum should be within 5 pixels or so of the "expected position" written to the template. Change the "expected position" to the actual maximum position and save wavecal.txt.

Then run wavelength_cal again, reading the edited wavecal.txt file:

wavelength_cal -i wavecal.txt -o active_calibration.txt

The reported correlation coefficient should be at least 0.9999. If it is less than this, something has gone wrong.

The wavelength_cal program will display how well the supplied wavelength / pixel coordinates are approximated by the linear function fitted to them.



Amplitude correction

Using a camera sensor from which the Bayer filter has been removed is a massive improvement over using a standard camera for a spectrometer. However, there are still effects that require correction if the relative amplitude of spectral features is to be measured. This is vital if colour related parameters are to be calculated from the spectra, although it isn't so important if transmission and reflectance spectra (which rely on ratios) or the locations of wavelength peaks are the main interest.

There are three effects which need to be corrected:

  • Sensor non-linearity. The sensor, being a camera, was originally designed to produce nice looking pictures. The sensor values will therefore not be linearly related to light intensity, but will assign more code values to lower light values to match how human vision works. It seems that using the inverse of the sRGB OETF on the values from this camera produces a good approximation to values linearly proportional to light intensity.
  • Etaloning. Spectra obtained from the device show very pronounced "oscillations" in amplitude with wavelength. This is most obvious with "smooth" spectra, such as from approximate blackbody radiators (tungsten lamps). There are reviews of the Little Garden spectrometer online which complain about this. These "oscillations" are due to interference effects caused by reflections from the glass window that protects the sensor.
  • Grating efficiency. Gratings do not "output" constant intensity with wavelength and the relationship is not simple in general. This is another source of distortion of measured spectra.

The linearisation is built in to specap and is a simple function (now the correct function has been identified).

Etaloning and grating efficiency correction is done by finding a wavelength dependent scaling factor which scales the (linearised) measurements so that they match a known spectrum. The known spectrum used is the output of a tungsten lamp, which is a very good approximation to a blackbody radiator.

A 60W light bulb run at its rated voltage (e.g. 220V) is very close to a 2600K blackbody. Unfortunately, tungsten light bulbs are now hard to find (I bought what was left locally 7 years ago (2019), since when they have been unavailable here). It is illegal to sell them in many places now, I believe (although not to own or use them!).

However, tungsten halogen "bead" bulbs (GU5.3 socket) are still widely used for non-domestic purposes, such as microscope illumination, and these can still be freely bought. A 12V 50W tungsten halogen "bead" lamp is a good approximation to a 3000K blackbody radiator. Unfortunately, it is necessary to provide a power supply and housing for these things, so they are not quite as easy to use as a domestic light bulb.

First capture the spectrum of the blackbody source without using any correction file:

specap -s specout.dat -n

As always, aim for a peak signal level between 0.8 and 0.9.

Then create the correction file using the correction_cal program:

correction_cal -s specout.dat -c correction.txt -t 2600

If a tungsten halogen "bead" lamp is used, the temperature should be changed to -t 3000.

The newly created correction file can be made active by copying it:

cp correction.txt /usr/local/lgscli/active_correction.txt

This will then be read by specap unless the -n option is supplied.

An example of an amplitude correction file is:



One problem with using a tungsten or tungsten halogen source for amplitude correction calculations is that these sources have very little blue output. This leads to some noise in the blue region of the correction curve.

However, having a source which is a very close match to a spectrum that can be calculated from physical principles is the only way to create a correction without already having another calibrated spectrometer that can measure the spectral output of some other source (such as a "daylight LED" lamp). If you do have another calibrated spectrometer, you could certainly use such sources instead and you might get less noisy correction curves in the blue region. This would require a modified version of correction_cal.py, which could read the expected reference spectrum.

As would be expected, the match of the corrected spectrum of a tungsten lamp to the calculated blackbody spectrum (at 2600K, red curve) is very good:



Note that the installation script installs a correction file created with my example of the Little Garden spectrometer, which may be helpful in "getting started". However, it is unlikely to exactly match any other Little Garden spectrometer, so using the amplitude correction procedure with your spectrometer is highly recommended, in spite of the probable difficulty of obtaining a suitable lamp.

Processing and display programs

plot_spectrum

Spectra captured by specap can be displayed using the plot_spectrum program. This has many options and can display single spectra or a set of spectra named in a file. In addition to the .dat format output by specap, the plot_spectrum program can also display spectra in the .json format produced by the TOBES-UI program which can be used to capture spectra from the Torch Bearer Y2 spectrometer. The TOBES-UI software can be found here.

The full set of options supported by plot_spectrum is:

--spec_in, -s : Spectral data input file (default: specout.dat).
--temperature, -t : Blackbody temperature.
--daylight, -d : Daylight temperature.
--log, -l : Log Y axis.
--visible, -v : Visible X range.
--files, -f : List of spectral data file names.
--normalise, -n : Normalise to 1.
--zero, -z : Include 0 on Y axis.
--export, -e : Save to SVG file.
--keys, -k : Use keys if files list.
--width, -w : Line width, 0.5 to 5, say.
--one, -1 : Include 1 on Y axis.
--pixel, -p : Pixel X axis.
--exclude, -x : Exclude some annotation.
--wrange, -r : Wavelength range, low,high.

Transmission and reflectance spectra can be measured by passing the light from a source with a known spectrum through a sample (or reflecting that light off a sample using a suitable geometric arrangement of the known light source and spectrometer), and taking the ratio of the transmitted (reflected) measured spectrum divided by the spectrum of the known light source.

ratio_spectrum

Calculating the ratio can be performed by the ratio_spectrum program, giving relative transmission or reflectance in the range 0 to 1. This program has the following options:

--ref, -r : Reference spectrum (active_reference.dat).
--measured, -m : Measured spectrum (specout.dat).
--output, -o, Ratio output spectrum. (ratio.dat).

Although making decent transmission spectrum measurements is fairly straightforward, obtaining good reflectance spectra is quite an art. The "45-0-45" geometry seems to be most often appropriate (giving the angular relationship between illuminant, sample and spectrometer in degrees) as this will usually minimise specular (glossy) reflection from the sample surface. But getting repeatable data is hard.

As with plot_spectrum, ratio_spectrum can read either .dat format spectral data from specap or .json spectral data from TOBES-UI. If the reference and measured spectra do not have the same wavelength range or sample interval, the spectra will both be interpolated and/or extrapolated to cover the range 380 nm to 780 nm at 1nm interval so that the ratio can be calculated.

get_cct

Finally, the program get_cct calculates a number of colour related parameters from a spectrum (.dat or .json format), including the Correlated Colour Temperature (CCT). This may or may not be appropriate, depending on what the spectrum is of. Other colour related parameters are CIE 1931 XYZ, x,y and L*,a*,b* with chroma C*.

Examples and tests

The spectra of a number of light sources were taken with the Little Garden spectrometer and the Torch Bearer Y2. The Y2 is even smaller than the Little Garden spectrometer and uses some quite innovative quantum dot technology.



Comparing the results is quite instructive. The Torch Bearer Y2 makes calibrated amplitude measurements in W/m^2/nm and the specification says this is accurate to within 3%. How well does the Little Garden spectrometer compare when used with amplitude correction?

Here is a direct comparison for a nominally 6500K "daylight" LED bulb and a nominally 3000K "warm" LED bulb:



That seems to be a very close match between the Little Garden and Y2 spectrometers. This plot was generated with:

plot_spectrum -f led-tb-srgb-comp.txt -n -k -e

A "daylight" fluorescent lamp also shows a good match, but it also shows that the Little Garden has much higher resolution than the Torch Bearer Y2 -- around 1nm (or better?) for the Little Garden versus 7nm for the Y2.



Here is a "warm" fluorescent lamp:



This is a halogen "bead" lamp (12V 50W):



Finally, this is an Eiko Solux 4700K 12V 35W "full range" tungsten halogen lamp that uses some fairly fancy filters to try to match a daylight-like spectrum. Unfortunately, these rather useful (if expensive) lamps have been discontinued as part of the war against tungsten lighting. It is possible that the voltage at the lamp terminals was a little low when this spectrum was taken.



Here is a comparison of CCTs for these sources calculated by get_cct from the Little Garden and Torch Bearer Y2 spectrometers. These are fairly close, apart from the fluorescent lamps, where the spectra do appear rather different due to the resolution difference between the two devices.

Light source LGS CCT Y2 CCT
6500K LED 5984K 6070K
3000K LED 2876K 2920K
6500K Fluorescent 6301K 6900K
3000K Fluorescent 2835K 2656K
Halogen bead 3085K 2958K
Eiko Solux 4700K 4307K 4476K

Here is a simple transmission spectrum calculated with ratio_spectrum. The reference illuminant was the halogen "bead" lamp, which has rather low blue output. The result is very believable, though.



This is the "sample":



Further information

Mr. Lao has several interesting videos on his spectrometer on YouTube. I also highly recommend the "Project 326" YouTube channel which has several videos on the Little Garden spectrometer, as well as the Torch Bearer Y2, and is very entertaining and informative.

Given that the Little Garden spectrometer can be obtained (at least in some areas) for around 60 GBP and the Torch Bearer Y2 for around 100 GBP, it seems to me that affordable and really useful visible light spectroscopy is a "solved problem" in 2026. This was not the case even 5 years ago, when you could expect to pay well over 1000 GBP for an instrument with capabilities similar to these devices.

About

Command line tools for the Little Garden spectrometer.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages