This repository has been trimmed to the essentials required to acquire a single scan from a DLP NIRScan Nano and save the result as a CSV using Python 3.11.2 on a Raspberry Pi 3B.
Files you will use:
NIRS.py— Python wrapper around the native_NIRScanner.soextension.scan_substance.py— acquisition script (per-scan 1D NumPy intensity array; optional CSV save toData/).build_native_pi.sh— helper to build the native shared object with a chosen Python executable.requirements.txt— Python packages required by the acquisition script.prune_unused.sh— optional script to remove demo/test files locally on the Pi to minimize repo footprint.systemd/nirscan.service— examplesystemdunit (edit paths to your venv/project).
Quick minimal setup (assumes you already have a tflite venv and want to reuse it)
-
Copy or clone this repo to your Pi and change to the project directory.
-
Ensure a matching
_NIRScanner.sois available in project root. To build it with your venv Python:
# run the build helper and give it the venv python executable
./build_native_pi.sh /path/to/venv/bin/python- Activate your existing venv and install dependencies:
source /path/to/venv/bin/activate
pip install -r requirements.txt- (Optional) Minimize repository on the Pi by removing demo/test files. Run this from the project root:
chmod +x prune_unused.sh
./prune_unused.sh- Run a scan and save CSV (use the venv python directly):
/path/to/venv/bin/python scan_substance.py --save-csv- (Optional) Run a scan and save as training data. Run this and replace "sugar" with your substance label. This will append that label to the csv file as a prefix:
/path/to/venv/bin/python python scan_substance.py --save-csv --prefix sugar- To run at boot, adapt the example in
systemd/nirscan.service(editExecStartandWorkingDirectoryto match your venv and project paths), then copy it to/etc/systemd/system/and enable it:
sudo cp systemd/nirscan.service /etc/systemd/system/nirscan.service
sudo systemctl daemon-reload
sudo systemctl enable --now nirscan.service
sudo journalctl -u nirscan.service -fNotes
- Keep
lib/andsrc/if you want to try prebuilt binaries or rebuild the native extension locally —build_native_pi.shwill compile against the provided Python executable. prune_unused.shwill prompt before deleting demo files; I left deletion under your control so you can verify everything on the Pi first.- If
_NIRScanner.sois not compatible with the venv Python (ABI mismatch), build with the venv python as shown above.
Quick setup
-
Ensure the compiled Python extension (
_NIRScanner.so) matching your Python version is available in the project root or onPYTHONPATH. Thelib/folder contains prebuilt binaries for some platforms. -
Install OS packages (Debian/Ubuntu/Raspbian):
sudo apt-get update
sudo apt-get install -y libudev-dev libusb-1.0-0-dev python3-dev python3-pip- (Optional) Create a virtualenv and install Python deps used by examples:
python3 -m venv .venv
.\\.venv\\Scripts\\activate # Windows (if testing on Windows)
source .venv/bin/activate # Linux / Raspberry Pi
pip install numpy pandas scipy pillow requests- If there is no
_NIRScanner.somatching your Python ABI inlib/, build the native extension using the included helper script:
# example: explicitly provide python executable
./build_native_pi.sh /usr/bin/python3.11
# or use default python3 on the Pi
./build_native_pi.shThe build script will run CMake and Make in the src/ folder and copy the resulting shared object to the project root as _NIRScanner.so.
Install Python dependencies into your venv (use the provided requirements.txt):
source .venv/bin/activate
pip install -r requirements.txtRunning a substance scan (example)
scan_substance.pyis an example script that:- Instantiates the
NIRSwrapper - Configures the device
- Performs a scan
- Returns scan information and saves a timestamped CSV to
Scans/
- Instantiates the
Example command (on the Pi):
python3 scan_substance.py --save-csvOutput:
-
The script prints a short summary to stdout (intensity shape, sample info) and saves a CSV to
~/Scans/(orScans/in earlier docs). The filename is either<timestamp>.csvor<prefix>-<timestamp>.csvwhen--prefixis provided. -
CSV layout: the saved file uses the legacy column layout expected by downstream training code. Columns (in this order) are:
header_versionscan_namescan_timetemperature_systemtemperature_detectorhumiditypgawavelengthintensityreferencevalid_lengthabsorbance(computed as-log10(intensity/reference)when reference is available; otherwise NaN)
-
The CSV is written with
pandas.DataFrame.to_csv(...)and currently includes the DataFrame index as the first column (to preserve legacy formatting). If you prefer no index column, run the script and I can change the code to writeindex=False. -
Example commands:
python scan_substance.py --save-csv # saves ~/Scans/<timestamp>.csv
python scan_substance.py --save-csv --prefix sugar # saves ~/Scans/sugar-<timestamp>.csv- To read the CSV with pandas:
import pandas as pd
df = pd.read_csv('~/Scans/sugar-20251210...csv')
print(df.columns)- Keep your substance-specific models separate from the scanner wrapper. Use
scan_substance.pyas the acquisition step and then pipe the returned 1D array into your analysis pipeline.
License & Notes
- This repo wraps vendor-provided binaries and code; check the original project and vendor licenses for redistribution constraints.