LESS 3.0
GPU + CPU accelerated 3D radiative transfer model for remote sensing simulation
LESS 3.0 is a complete reimplementation of the LESS model — a widely-used 3D radiative transfer framework in quantitative remote sensing research. Built around NVIDIA OptiX, cross-vendor Vulkan Ray Query, Intel Embree, and a modern Python API, LESS 3.0 inherits the physical foundations of the original LESS while adding hardware acceleration, a redesigned scripting interface, and full physical coupling of energy balance, photosynthesis, and solar-induced chlorophyll fluorescence (SIF).
The original LESS remains available at lessrt.org. LESS 3.0 is the recommended path for new projects.
Key Features
- End-to-end satellite imaging — Pushbroom motion and per-pixel geometry, native atmospheric propagation, spectral response, PSF/MTF, detector noise, ADC quantisation, and geolocation in one simulation chain.
- Three compute backends — OptiX is the high-performance NVIDIA path, Vulkan Ray Query provides experimental cross-vendor GPU coverage, and Embree supplies portable CPU workflows.
- Clean Python API — Designed for remote sensing scientists. Build a scene in 10 lines of code.
- Digital twin architecture — Build the scene once, simulate many times. Update illumination or surface properties without rebuilding geometry.
- Multi-sensor support — Optical, thermal infrared, LiDAR point cloud/waveform, SIF fluorescence, and passive/active microwave sensors.
- Full physical coupling — 3D radiation field → energy balance → photosynthesis → SIF, all tightly coupled to the Monte Carlo ray tracing engine.
- Interactive 3D viewer —
scene.show()opens a browser-based viewer to inspect the scene and preview simulation results.
Installation
pip install less3d
Pre-built wheels for Windows and Linux are provided for Python 3.10–3.13. No compiler, CUDA toolkit, or additional runtime installation required.
| CPU | Cross-vendor GPU | NVIDIA GPU | |
|---|---|---|---|
| Backend | Embree | Vulkan Ray Query | OptiX + CUDA |
| Hardware | Modern x86-64 | Vulkan 1.2 Ray Query GPU | Compatible NVIDIA GPU |
| Memory | System RAM | 4 GB+ VRAM recommended | 8 GB+ VRAM recommended |
| Best use | Portable core workflows | Portability and validation | Production Monte Carlo |
| Python | 3.10–3.13 | 3.10–3.13 | 3.10–3.13 |
Feature coverage differs by backend. Use
less.can_use("feature")orscene.can_use("feature")for the final answer in the current installation.
Backend feature matrix
OK means the workflow is implemented by a non-experimental backend.
Experimental means it is implemented and covered by cross-backend regression
tests, but the Vulkan backend is still being optimized and may be substantially
slower than OptiX. -- means that backend does not implement the workflow.
| User workflow | OptiX + CUDA | Vulkan Ray Query | Embree CPU |
|---|---|---|---|
| Optical imaging | OK | Experimental | OK |
| Thermal-infrared imaging | OK | Experimental | OK |
| Per-primitive thermal temperatures | OK | Experimental | OK |
| SIF imaging | OK | Experimental | OK |
| Directional BRF / albedo | OK | Experimental | OK |
| 3D radiation field / fPAR | OK | Experimental | OK |
| Irradiance maps | OK | Experimental | OK |
| LiDAR point cloud | OK | Experimental | OK |
| Full-waveform LiDAR | OK | Experimental | OK |
| Energy balance | OK | Experimental | OK |
| Per-primitive spectral radiation process | OK | Experimental | OK |
| Photosynthesis process | OK | Experimental | OK |
| SIF process | OK | Experimental | OK |
| Passive microwave brightness temperature | OK | Experimental | OK |
| Active microwave radar backscatter | OK | Experimental | OK |
| Dynamic instance updates | OK | Experimental | OK |
| Periodic / repetitive scenes | OK | Experimental | OK |
| Terrain-following sensing | OK | Experimental | OK |
The table describes code coverage, not the hardware in a particular computer. For the single user-facing answer on the current machine, call for example:
less.can_use("lidar_waveform", backend="vulkan")
scene.can_use("energy_balance")
On NVIDIA hardware, use OptiX for production simulations. Vulkan is currently intended for cross-vendor access, validation, and backend development; it is not yet a performance replacement for the CUDA kernels.
Quick Start
import less
# Create a 10 m × 10 m bare-soil scene
scene = less.Scene()
scene.size = 10.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.3))
scene.illumination = less.DirectDiffuse(sun_zenith=30, sun_azimuth=150)
scene.build()
# Simulate a nadir RGB image
image = scene.simulate(less.OpticalImager(
less.Orthographic(image_size=256),
bands=[650, 550, 450], # R, G, B (nm)
quality=128,
))
image.save("output.png")
Thanks to the digital twin architecture, updating scene parameters does not require a rebuild:
# Change sun angle and re-simulate — no rebuild needed
scene.illumination = less.DirectDiffuse(sun_zenith=60, sun_azimuth=90)
image2 = scene.simulate(sensor)
Simulation Capabilities
| Domain | What you can simulate |
|---|---|
| Satellite imaging | Local-track pushbroom acquisition, TOA atmosphere, instrument response, detector DN and per-pixel geolocation |
| Optical | RGB, multispectral, and hyperspectral images; BRF / BRDF angular sampling; NDVI and vegetation indices |
| Thermal infrared | Per-component temperature scenes (sunlit/shaded leaf, soil, trunk); thermal radiance images |
| LiDAR | Airborne laser scanning (ALS) and terrestrial laser scanning (TLS) point clouds and full waveforms |
| Vegetation physiology | 3D PAR radiation field, full energy balance, photosynthesis, solar-induced chlorophyll fluorescence (SIF) imaging |
| Microwave | Passive H/V brightness temperature and active HH/HV/VH/VV radar backscatter, including vegetation and trunk-ground interactions |
Forest Scene Example
import less
import numpy as np
scene = less.Scene()
scene.size = 30.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.12))
scene.illumination = less.DirectDiffuse(sun_zenith=35, sun_azimuth=225)
# Broadleaf tree with PROSPECT leaf optical properties
birch = less.Object("birch", mesh="birch.obj")
birch.set_property("leaves", less.Prospect(cab=40, car=8, cw=0.012, cm=0.009, N=1.5))
# Random planting positions
xy = np.random.rand(50, 2) * 30
positions = np.c_[xy, np.zeros(50)]
scene.add(birch, positions=positions)
scene.build()
# Multispectral image (green, red, NIR)
image = scene.simulate(less.OpticalImager(
less.Orthographic(image_size=512),
bands=[550, 670, 800],
quality=256,
))
image.save("forest.tif") # GeoTIFF preserves physical radiance values
Built-in Examples and Viewer
import less
less.examples.list() # list all built-in scenes
less.examples.run("autumn_forest") # launch interactive viewer
less.examples.run("maize_field")
scene.show() # open 3D viewer in browser (Scene / Simulate / Products tabs)
Validation
LESS 3.0 is cross-validated against the original LESS on reference scenes:
| Scene | Description | Max RRMSE |
|---|---|---|
| Val01 | Lambertian ground | 0.02% |
| Val02 | Box canopy | 0.22% |
| Val03 | Ellipsoid forest | 0.83% |
| Val04 | Forest + diffuse sky | 2.17% |
| Val05 | PROSPECT-D leaves | 0.24% |
| Val06 | fPAR vs sun zenith angle | 0.62% |
| Val07 | Thermal IR | 0.17% |
Full validation reports are regenerated on each release. See tests/validation/.
Backend LiDAR throughput and CPU/GPU crossover can be reproduced with:
python benchmarks/benchmark_lidar_scaling.py
The benchmark reports fast point-cloud and full-waveform throughput at 1 thousand through 1 million pulses and checks numerical agreement against the Embree backend.
Documentation and Tutorials
Full documentation with step-by-step tutorials:
Topics covered: coordinate system · terrain and surface properties · illumination models · optical imaging · BRDF/BRF sampling · thermal infrared · LiDAR · energy balance · photosynthesis · SIF · visualization · scene serialization
Citing
If you use LESS 3.0 in your research, please cite the original LESS paper:
Qi, J., Xie, D., Yin, T., Yan, G., Gastellu-Etchegorry, J.P., Li, L., Zhang, W., Mu, X., Norford, L.K. (2019). LESS: LargE-Scale remote sensing data and image Simulation framework over heterogeneous 3D scenes. Remote Sensing of Environment, 221, 695–706.
Metadata
Release files for less3d 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| less3d-0.5.0-cp313-cp313-win_amd64.whl | CPython 3.13 | CPython 3.13 | Windows x86-64 | Details |
| less3d-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 | Details |
| less3d-0.5.0-cp312-cp312-win_amd64.whl | CPython 3.12 | CPython 3.12 | Windows x86-64 | Details |
| less3d-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| less3d-0.5.0-cp311-cp311-win_amd64.whl | CPython 3.11 | CPython 3.11 | Windows x86-64 | Details |
| less3d-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | CPython 3.11 | CPython 3.11 | Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 | Details |
| less3d-0.5.0-cp310-cp310-win_amd64.whl | CPython 3.10 | CPython 3.10 | Windows x86-64 | Details |
| less3d-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | CPython 3.10 | CPython 3.10 | Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 | Details |
Total release size: 345.9 MB
Release files / less3d-0.5.0-cp313-cp313-win_amd64.whl
| Download URL | less3d-0.5.0-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 28.1 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
4e2a7e8538b9f5a0a35edc995fd2368873788cf580cbb60374f9e82089a3192c
|
|
BLAKE2b-256 checksum How to use checksums |
3b7b65d5325178a44f58c0cb44bafcb8273e539411778ebf0fa6e7ea9f6683cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | less3d-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 58.4 MB |
| Tags | CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
0206219b1c43fc12db2cbf0b39f40365ee2e9f176a2489cc35db65dbb39f73b7
|
|
BLAKE2b-256 checksum How to use checksums |
e4f382552ff26f4dad16aae262d5d153ee75ea12e473f37c30a2063c789ae81f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp312-cp312-win_amd64.whl
| Download URL | less3d-0.5.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 28.1 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e7a1f55e9647e1316c7bc4168cb7b7b73ff6272c77e7969248dabd6c05d179a3
|
|
BLAKE2b-256 checksum How to use checksums |
fac1116b98bd9544f4bdf4f044c5b968a3ad3d66ff4a56cfa2be9581afd532b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | less3d-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 58.4 MB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
c2b3689b65312bf2be9b925915ce701fb18d1fa361cfc599ed0f9af9eda25f6a
|
|
BLAKE2b-256 checksum How to use checksums |
6a134082c92936a0b0a12539e34a117fe85dd16a3e76a92eaca07682e2da3f5b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp311-cp311-win_amd64.whl
| Download URL | less3d-0.5.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 28.1 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
6fde1cbc7770864e6afca92326caa97f4f6e2142d2f629d7622a8ea5d0649cfe
|
|
BLAKE2b-256 checksum How to use checksums |
da84ac170254866b112c990ba4e4951c790ab2e546c6fdd607360f0cf324693d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | less3d-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 58.4 MB |
| Tags | CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
386c611d8894df216a54fe5ddbb331d7f01dffc7fa2d13fd26d21b6890254b29
|
|
BLAKE2b-256 checksum How to use checksums |
66c677fcda7aebe8da0a0f56f65af6a19bab270154f0ff73e90d244bcb28a52a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp310-cp310-win_amd64.whl
| Download URL | less3d-0.5.0-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 28.1 MB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
806abbb8268f204e2ac0d2861184a43c1fae57c2d46077abbc985b3c5ae8322e
|
|
BLAKE2b-256 checksum How to use checksums |
48db07cea4bfd2e6d8ddfcc3b0b2ee0b1f1a789bea33e92c9d05794bbd000b2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / less3d-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | less3d-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 58.4 MB |
| Tags | CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
8a18694dddb569ad7939e178a3069d2b971ee892fc49d8ffc296403ab15d242d
|
|
BLAKE2b-256 checksum How to use checksums |
eeda897d7c11f768a3e6f4f305f619ff095e5f551d18f1628234fe3c0dc5aa4f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|