Skip to content

Commit 01b0b16

Browse files
committed
[v0.1.16] 2026-03-12
- Updated helios-core to v1.3.67 ## Context - Added primitive texture management methods: `getPrimitiveTextureFile()`, `setPrimitiveTextureFile()`, `getPrimitiveTextureSize()`, `getPrimitiveTextureUV()`, `primitiveTextureHasTransparencyChannel()`, `getPrimitiveSolidFraction()`, `overridePrimitiveTextureColor()`, `usePrimitiveTextureColor()`, `isPrimitiveTextureColorOverridden()` - Primitive getters now accept a list of UUIDs for efficient batch queries returning NumPy arrays (e.g., `getPrimitiveNormal([uuid1, uuid2])` returns an ndarray of shape (N, 3)) - Added `getAll*` convenience methods that query all primitives in the context (e.g., `getAllPrimitiveNormals()`) - Extended `PrimitiveInfo` with `texture_file`, `texture_uv`, and `solid_fraction` fields - Added timeseries data management: `addTimeseriesData()`, `setCurrentTimeseriesPoint()`, `queryTimeseriesData()`, `queryTimeseriesDate()`, `queryTimeseriesTime()`, `getTimeseriesLength()`, `doesTimeseriesVariableExist()`, `listTimeseriesVariables()`, `loadTabularTimeseriesData()` ## Radiation Model - Added EXR image export methods: `writeCameraImageDataEXR()`, `writeDepthImageData()`, `writeDepthImageDataEXR()`, `writeNormDepthImage()` - Added `getBackendName()` and `probeAnyGPUBackend()` for runtime GPU backend detection - Updated error messages to reflect runtime backend auto-detection (OptiX 8 -> OptiX 6 -> Vulkan) ## Validation - Added `isinstance()`-based type validation to PlantArchitecture and RadiationModel methods per argument type validation policy - Added `validate_position_like()`, `validate_direction_like()`, and `validate_size_like()` validators for flexible parameter types
1 parent e9a2b85 commit 01b0b16

25 files changed

Lines changed: 3781 additions & 628 deletions

.github/workflows/build-wheels.yml

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ jobs:
2525
- name: Set package version from tag
2626
if: startsWith(github.ref, 'refs/tags/')
2727
shell: bash
28-
run: echo "SETUPTOOLS_SCM_PRETEND_VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV"
28+
run: |
29+
VERSION="${GITHUB_REF_NAME#v}"
30+
# PyPI permanently reserves filenames for deleted releases.
31+
# Use .postN suffix for versions whose files were previously uploaded and deleted.
32+
case "$VERSION" in
33+
0.1.16) VERSION="0.1.16.post1" ;;
34+
esac
35+
echo "SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION}" >> "$GITHUB_ENV"
2936
3037
- name: Checkout PyHelios
3138
uses: actions/checkout@v4
@@ -199,8 +206,8 @@ jobs:
199206
run: python -m cibuildwheel --output-dir wheelhouse
200207
timeout-minutes: 60 # Increased for LiDAR tests which are comprehensive
201208
env:
202-
# Build for Python 3.9+ on all platforms
203-
CIBW_BUILD: cp39-* cp310-* cp311-* cp312-* cp313-*
209+
# Build for Python 3.10+ on all platforms
210+
CIBW_BUILD: cp310-* cp311-* cp312-* cp313-* cp314-*
204211

205212
# Fail fast on build errors instead of continuing to next Python version
206213
CIBW_BUILD_VERBOSITY: 1
@@ -272,7 +279,7 @@ jobs:
272279
yum install -y zlib-devel mesa-libGL-devel mesa-libEGL-devel libX11-devel libXrandr-devel mesa-libGLU-devel libXinerama-devel libXcursor-devel libXi-devel libXxf86vm-devel &&
273280
export PKG_CONFIG_PATH="/usr/lib64/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" &&
274281
export CMAKE_PREFIX_PATH="/usr:${CMAKE_PREFIX_PATH}" &&
275-
/opt/python/cp39-cp39/bin/python build_scripts/prepare_wheel.py --buildmode release --verbose --clean
282+
/opt/python/cp310-cp310/bin/python build_scripts/prepare_wheel.py --buildmode release --verbose --clean
276283
# Per-ABI: do not rebuild; only stage/copy already built artifacts
277284
CIBW_BEFORE_BUILD_LINUX: >
278285
if [ -f /opt/rh/devtoolset-10/enable ]; then
@@ -290,7 +297,7 @@ jobs:
290297
export PKG_CONFIG_PATH="/usr/lib64/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH}" &&
291298
export CMAKE_PREFIX_PATH="/usr:${CMAKE_PREFIX_PATH}" &&
292299
echo "Reusing native build; packaging only." &&
293-
/opt/python/cp39-cp39/bin/python build_scripts/prepare_wheel.py --buildmode release --verbose
300+
/opt/python/cp310-cp310/bin/python build_scripts/prepare_wheel.py --buildmode release --verbose
294301
295302
# Manylinux-specific environment for zlib compatibility and OpenGL discovery
296303
# Use documented $PATH expansion to append devtoolset without overriding cibuildwheel's Python
@@ -701,15 +708,15 @@ jobs:
701708
matrix:
702709
include:
703710
- os: ubuntu-22.04
704-
python-version: '3.9'
711+
python-version: '3.10'
705712
- os: ubuntu-22.04
706-
python-version: '3.13'
713+
python-version: '3.14'
707714
- os: windows-2022
708-
python-version: '3.9'
715+
python-version: '3.10'
709716
- os: windows-2022
710-
python-version: '3.13'
717+
python-version: '3.14'
711718
- os: macos-14
712-
python-version: '3.13'
719+
python-version: '3.14'
713720

714721
steps:
715722
- name: Checkout PyHelios for tests
@@ -1299,8 +1306,18 @@ jobs:
12991306
merge-multiple: true
13001307
path: wheelhouse
13011308

1309+
- name: List wheel sizes
1310+
run: |
1311+
echo "=== Wheel sizes (PyPI limit: 100MB default) ==="
1312+
ls -lhS wheelhouse/
1313+
echo ""
1314+
echo "=== Wheels exceeding 100MB ==="
1315+
find wheelhouse/ -name "*.whl" -size +100M -exec ls -lh {} \; || echo "None found"
1316+
13021317
- name: Publish to PyPI
13031318
uses: pypa/gh-action-pypi-publish@release/v1
13041319
with:
13051320
packages-dir: wheelhouse/
13061321
verify-metadata: false # Skip metadata verification due to dynamic versioning
1322+
skip-existing: true # Allow re-runs without failing on already-uploaded wheels
1323+
verbose: true # Show full PyPI error details on upload failure

README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ See the Helios C++ documentation for a more in-depth description of Helios: http
2525

2626
### Installation
2727

28+
**Requirements:** Python 3.10 or later (pre-built wheels available for Python 3.10–3.14)
29+
2830
**Easy Install (Recommended):**
2931
```bash
3032
pip install pyhelios3d
@@ -50,7 +52,7 @@ If you need to customize plugins or build from source:
5052

5153
**Prerequisites:**
5254
- Visual Studio 2019+ or Build Tools for Visual Studio
53-
- Python 3.7+
55+
- Python 3.10+
5456

5557
```bash
5658
# Clone repository
@@ -68,7 +70,7 @@ pip install -e .
6870

6971
**Prerequisites:**
7072
- Xcode command line tools
71-
- Python 3.7+
73+
- Python 3.10+
7274

7375
```bash
7476
# Install Xcode command line tools
@@ -91,7 +93,7 @@ pip install -e .
9193
**Prerequisites:**
9294
- Build essentials
9395
- CMake
94-
- Python 3.7+
96+
- Python 3.10+
9597

9698
```bash
9799
# Clone repository
@@ -121,9 +123,11 @@ PyHelios plugins have three types of GPU support:
121123
**CPU-Only Plugins** (no GPU needed):
122124
- All other plugins (PlantArchitecture, Photosynthesis, SolarPosition, etc.)
123125

124-
**For GPU Acceleration** (optional), ensure you have:
125-
- Vulkan SDK installed (supports NVIDIA, AMD, Intel, Apple Silicon GPUs)
126-
- OR for NVIDIA-optimized path: CUDA Toolkit (version 11.8 or 12.x) + OptiX
126+
**For GPU Acceleration** (optional), ensure you have at least one:
127+
- Vulkan loader library (macOS/Linux only; no extra packages on Windows)
128+
- OR for NVIDIA-optimized path: CUDA 12.0+ with driver >= 560 (OptiX 8.1) or CUDA 9.0+ with driver < 560 (OptiX 6.5)
129+
130+
The radiation plugin auto-detects the best available backend at runtime (OptiX 8 -> OptiX 6 -> Vulkan).
127131

128132
**Verification:**
129133
```bash

build_scripts/build_helios.py

Lines changed: 3 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -780,13 +780,8 @@ def run_cmake_configure(self, additional_args: Optional[List[str]] = None) -> No
780780
'-DBUILD_SHARED_LIBS=ON', # Build as shared library on Unix
781781
])
782782

783-
# Windows-specific workaround for zlib resource compilation issue
783+
# Windows-specific: disable resource compilation if CMAKE_RC_COMPILER is not set
784784
if self.platform_name == 'Windows':
785-
# The RC compiler fails on win32/zlib1.rc due to C syntax in included headers
786-
# Patch zlib CMakeLists.txt to disable the problematic shared library target
787-
self._patch_zlib_cmake_for_windows()
788-
789-
# Disable resource compilation entirely if CMAKE_RC_COMPILER is not set
790785
if not os.environ.get('CMAKE_RC_COMPILER'):
791786
cmake_cmd.extend(['-DCMAKE_RC_COMPILER=']) # Empty RC compiler disables resource compilation
792787

@@ -1477,8 +1472,8 @@ def copy_radiation_shader_files(self) -> None:
14771472
"The radiation plugin requires GPU backend shader files.\n"
14781473
"Shader files (SPIR-V for Vulkan, PTX for OptiX) should be generated during CMake build.\n\n"
14791474
"To fix this issue:\n"
1480-
"1. Ensure Vulkan SDK is installed (primary cross-platform backend)\n"
1481-
"2. Or ensure CUDA toolkit + OptiX are installed (NVIDIA-only backend)\n"
1475+
"1. Ensure Vulkan loader is installed (macOS/Linux; bundled on Windows)\n"
1476+
"2. Or ensure CUDA toolkit is installed (NVIDIA GPU backend)\n"
14821477
"3. Check CMake configuration enables at least one GPU backend\n"
14831478
"4. Run build with --clean to rebuild from scratch\n\n"
14841479
f"Expected shader directory: {shader_source_dir}\n"
@@ -1572,70 +1567,6 @@ def build(self, cmake_args: Optional[List[str]] = None) -> Path:
15721567
print(f"Built with plugins: {final_plugins}")
15731568
return output_library
15741569

1575-
def _patch_zlib_cmake_for_windows(self) -> None:
1576-
"""
1577-
Patch zlib's CMakeLists.txt on Windows to disable the shared library target
1578-
that causes resource compilation errors with win32/zlib1.rc.
1579-
"""
1580-
zlib_cmake_path = self.helios_root / "core" / "lib" / "zlib" / "CMakeLists.txt"
1581-
1582-
if not zlib_cmake_path.exists():
1583-
print("Warning: zlib CMakeLists.txt not found, skipping patch")
1584-
return
1585-
1586-
print("Patching zlib CMakeLists.txt to disable shared library on Windows...")
1587-
1588-
try:
1589-
# Read the original file
1590-
with open(zlib_cmake_path, 'r') as f:
1591-
content = f.read()
1592-
1593-
# Check if already patched (to avoid double-patching)
1594-
if "# PYHELIOS PATCH: Disabled shared library" in content:
1595-
print("zlib CMakeLists.txt already patched")
1596-
return
1597-
except Exception as e:
1598-
print(f"Warning: Failed to read zlib CMakeLists.txt: {e}")
1599-
return
1600-
1601-
# Patch: comment out the shared library creation and related lines
1602-
patches = [
1603-
# Comment out the shared library creation
1604-
("add_library(zlib SHARED", "# PYHELIOS PATCH: Disabled shared library\n# add_library(zlib SHARED"),
1605-
# Comment out the include directories for shared lib
1606-
("target_include_directories(zlib PUBLIC", "# target_include_directories(zlib PUBLIC"),
1607-
# Comment out all properties for shared lib
1608-
("set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)", "# set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)"),
1609-
("set_target_properties(zlib PROPERTIES SOVERSION 1)", "# set_target_properties(zlib PROPERTIES SOVERSION 1)"),
1610-
(" set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})", " # set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})"),
1611-
(" set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)", " set_target_properties(zlibstatic PROPERTIES OUTPUT_NAME z)"),
1612-
(" set_target_properties(zlib PROPERTIES LINK_FLAGS", " # set_target_properties(zlib PROPERTIES LINK_FLAGS"),
1613-
(" set_target_properties(zlib PROPERTIES SUFFIX \"1.dll\")", " # set_target_properties(zlib PROPERTIES SUFFIX \"1.dll\")"),
1614-
# Update install targets to exclude zlib shared library
1615-
(" install(TARGETS zlib zlibstatic", " install(TARGETS zlibstatic"),
1616-
# Add static runtime linking for zlib
1617-
("add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})",
1618-
"add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})\n# PYHELIOS PATCH: Use static MSVC runtime\nif(MSVC)\n set_target_properties(zlibstatic PROPERTIES MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>\")\nendif()"),
1619-
# Disable problematic resource compilation
1620-
("if(NOT MINGW)\n set(ZLIB_DLL_SRCS\n win32/zlib1.rc # If present will override custom build rule below.\n )\nendif()",
1621-
"# PYHELIOS PATCH: Disable resource compilation to avoid RC errors\n# if(NOT MINGW)\n# set(ZLIB_DLL_SRCS\n# win32/zlib1.rc # If present will override custom build rule below.\n# )\n# endif()"),
1622-
]
1623-
1624-
for old, new in patches:
1625-
if old in content:
1626-
content = content.replace(old, new)
1627-
print(f" Patched: {old[:50]}...")
1628-
1629-
# Write the patched file back
1630-
try:
1631-
with open(zlib_cmake_path, 'w') as f:
1632-
f.write(content)
1633-
print("zlib CMakeLists.txt patched successfully")
1634-
except Exception as e:
1635-
print(f"Warning: Failed to write patched zlib CMakeLists.txt: {e}")
1636-
raise HeliosBuildError(f"Could not patch zlib CMakeLists.txt: {e}")
1637-
1638-
16391570
def get_default_plugins() -> List[str]:
16401571
"""
16411572
Get the default set of plugins (only the currently integrated plugins).

docs/CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Changelog
22

3+
# [v0.1.16] 2026-03-12
4+
5+
- Updated helios-core to v1.3.67
6+
7+
## Context
8+
- Added primitive texture management methods: `getPrimitiveTextureFile()`, `setPrimitiveTextureFile()`, `getPrimitiveTextureSize()`, `getPrimitiveTextureUV()`, `primitiveTextureHasTransparencyChannel()`, `getPrimitiveSolidFraction()`, `overridePrimitiveTextureColor()`, `usePrimitiveTextureColor()`, `isPrimitiveTextureColorOverridden()`
9+
- Primitive getters now accept a list of UUIDs for efficient batch queries returning NumPy arrays (e.g., `getPrimitiveNormal([uuid1, uuid2])` returns an ndarray of shape (N, 3))
10+
- Added `getAll*` convenience methods that query all primitives in the context (e.g., `getAllPrimitiveNormals()`)
11+
- Extended `PrimitiveInfo` with `texture_file`, `texture_uv`, and `solid_fraction` fields
12+
- Added timeseries data management: `addTimeseriesData()`, `setCurrentTimeseriesPoint()`, `queryTimeseriesData()`, `queryTimeseriesDate()`, `queryTimeseriesTime()`, `getTimeseriesLength()`, `doesTimeseriesVariableExist()`, `listTimeseriesVariables()`, `loadTabularTimeseriesData()`
13+
14+
## Radiation Model
15+
- Added EXR image export methods: `writeCameraImageDataEXR()`, `writeDepthImageData()`, `writeDepthImageDataEXR()`, `writeNormDepthImage()`
16+
- Added `getBackendName()` and `probeAnyGPUBackend()` for runtime GPU backend detection
17+
- Updated error messages to reflect runtime backend auto-detection (OptiX 8 -> OptiX 6 -> Vulkan)
18+
19+
## Validation
20+
- Added `isinstance()`-based type validation to PlantArchitecture and RadiationModel methods per argument type validation policy
21+
- Added `validate_position_like()`, `validate_direction_like()`, and `validate_size_like()` validators for flexible parameter types
22+
323
# [v0.1.15] 2026-03-06
424

525
- Updated helios-core to v1.3.65

docs/cross_platform.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
PyHelios is designed to work seamlessly across Windows, macOS, and Linux. This guide covers platform-specific considerations and features.
44

5+
## Python Version Support
6+
7+
PyHelios requires **Python 3.10 or later**. Pre-built wheels are available for Python 3.10–3.14.
8+
9+
| Python Version | Status |
10+
|----------------|--------|
11+
| 3.10 – 3.14 | Supported (pre-built wheels available) |
12+
| 3.9 and earlier | Not supported |
13+
514
## Platform Support Matrix
615

716
| Feature | Windows | macOS | Linux | Notes |

0 commit comments

Comments
 (0)