Skip to content

Commit 1e67277

Browse files
committed
[v0.0.1] 2025-08-21
## Helios native C++ Fix helios-core submodule to point to correct remote commit - Reset submodule to match actual remote state (228a3d389) - Remove local divergent commits that don't exist on remote - This fixes the git history display showing non-existent commits ## Context - Add primitive data operations for all types (float, int, string, vec2/3/4, int2/3/4) - Add primitive data query functions (exists, type, size) - Add auto-detection getter and pseudo-color visualization support - Extend Context.py with comprehensive primitive data methods - Add robust error handling and cross-platform ctypes wrappers - Include comprehensive test coverage for all primitive data operations - Added Context::getPrimitiveDataArray() to return a numpy array of primitive data
1 parent dbe14c6 commit 1e67277

13 files changed

Lines changed: 2051 additions & 275 deletions

File tree

README.md

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Test Linux](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-linux.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-linux.yml) [![Test Windows](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-windows.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-windows.yml) [![Test MacOS](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-macos.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-macos.yml) [![Docs](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/docs.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/docs.yml)
44

55
<div align="center">
6-
<img src="docs/images/PyHelios_logo_whiteborder.png" alt="" width="300" />
6+
<img src="https://raw.githubusercontent.com/PlantSimulationLab/PyHelios/master/docs/images/PyHelios_logo_whiteborder.png" alt="" width="300" />
77
</div>
88

99
# PyHelios
@@ -123,24 +123,18 @@ from pyhelios.RadiationModel import RadiationModelError
123123
context = Context()
124124
# Add geometry (PLY files, patches, trees, etc.)
125125

126-
try:
127-
# RadiationModel automatically checks plugin availability
128-
with RadiationModel(context) as radiation:
129-
radiation.addRadiationBand("SW")
130-
radiation.setDirectRayCount("SW", 100)
131-
radiation.setDiffuseRayCount("SW", 300)
126+
with RadiationModel(context) as radiation:
127+
radiation.addRadiationBand("SW")
128+
radiation.setDirectRayCount("SW", 100)
129+
radiation.setDiffuseRayCount("SW", 300)
132130

133-
# Run GPU simulation
134-
radiation.runBand("SW")
135-
results = radiation.getTotalAbsorbedFlux()
131+
# Run GPU simulation
132+
radiation.runBand("SW")
133+
results = radiation.getTotalAbsorbedFlux()
136134

137-
# Apply native pseudocolor mapping for visualization
138-
all_uuids = context.getAllUUIDs()
139-
context.colorPrimitiveByDataPseudocolor(all_uuids, "radiation_flux_SW", "hot", 256)
140-
141-
except RadiationModelError as e:
142-
print(f"Radiation modeling not available: {e}")
143-
# Error includes specific instructions for enabling radiation plugin
135+
# Apply native pseudocolor mapping for visualization
136+
all_uuids = context.getAllUUIDs()
137+
context.colorPrimitiveByDataPseudocolor(all_uuids, "radiation_flux_SW", "hot", 256)
144138
```
145139

146140
### Command-Line Plugin Tools
@@ -179,39 +173,17 @@ pytest --cov=pyhelios
179173

180174
PyHelios now supports **flexible plugin selection** for customized builds based on your hardware and requirements. Choose from **21 available plugins** using predefined profiles or explicit selection.
181175

182-
### Quick Start with Profiles
183-
184-
```bash
185-
# Minimal build (core functionality only)
186-
build_scripts/build_helios --profile minimal
187-
188-
# Standard build (recommended for most users)
189-
build_scripts/build_helios --profile standard
190-
191-
# GPU-accelerated build (requires CUDA for radiation modeling)
192-
build_scripts/build_helios --profile gpu-accelerated
193-
194-
# Full research suite (comprehensive plugin set)
195-
build_scripts/build_helios --profile research
196-
```
197-
198176
### Advanced Plugin Selection
199177

200178
```bash
201179
# Custom plugin selection
202-
build_scripts/build_helios --plugins weberpenntree,canopygenerator,visualizer,energybalance
180+
build_scripts/build_helios --plugins weberpenntree,visualizer
203181

204182
# Interactive selection (guided setup)
205183
build_scripts/build_helios --interactive
206184

207185
# Exclude problematic plugins
208-
build_scripts/build_helios --profile standard --exclude radiation
209-
210-
# Discover optimal configuration for your system
211-
python -m pyhelios.plugins discover
212-
213-
# Check plugin status and availability
214-
python -m pyhelios.plugins status
186+
build_scripts/build_helios --exclude radiation
215187
```
216188

217189
### Configuration File Support
@@ -240,16 +212,6 @@ plugins:
240212
241213
## Troubleshooting
242214
243-
### Native Library Requirements
244-
- **Problem**: Operations raise "mock mode" or "native library required" errors
245-
- **Solution**: Build and install native libraries using `build_scripts/build_helios`
246-
- **Note**: PyHelios requires native libraries for full functionality - mock mode is only for development/testing
247-
248-
### Build Issues
249-
- **Windows**: Ensure Visual Studio or Build Tools are installed
250-
- **macOS**: Install Xcode command line tools with `xcode-select --install`
251-
- **Linux**: Install build essentials with `sudo apt-get install build-essential cmake`
252-
253215
### Import Errors
254216
- Verify installation: `pip list | grep pyhelios`
255217
- Check Python version: Requires Python 3.7+

build_scripts/build_helios.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,26 +1399,30 @@ def _patch_zlib_cmake_for_windows(self) -> None:
13991399

14001400
def get_default_plugins() -> List[str]:
14011401
"""
1402-
Get the default set of plugins (all non-GPU-compute plugins, including visualization).
1402+
Get the default set of plugins (only the 3 currently integrated plugins).
14031403
1404-
Note: Visualization plugins like 'visualizer' only require OpenGL, not specialized
1405-
GPU compute APIs like CUDA/OptiX, so they should be included by default.
1404+
Currently only 3 plugins are integrated into PyHelios:
1405+
- visualizer: OpenGL-based 3D visualization
1406+
- weberpenntree: Procedural tree generation
1407+
- radiation: OptiX-accelerated ray tracing (GPU optional)
14061408
14071409
Returns:
14081410
List of default plugins
14091411
"""
1412+
# Only return the 3 plugins that are actually integrated into PyHelios
1413+
integrated_plugins = ["visualizer", "weberpenntree", "radiation"]
1414+
1415+
# Filter by platform compatibility
14101416
default_plugins = []
1411-
for name, metadata in PLUGIN_METADATA.items():
1412-
# Include if it's platform compatible and doesn't require specialized GPU compute
1413-
platform_name = platform.system().lower()
1414-
if platform_name == "darwin":
1415-
platform_name = "macos"
1416-
1417-
if platform_name in metadata.platforms:
1418-
# Only exclude plugins that require specialized GPU compute (CUDA/OptiX)
1419-
# OpenGL-based visualization is not considered "GPU compute"
1420-
if not metadata.gpu_required:
1421-
default_plugins.append(name)
1417+
platform_name = platform.system().lower()
1418+
if platform_name == "darwin":
1419+
platform_name = "macos"
1420+
1421+
for plugin in integrated_plugins:
1422+
if plugin in PLUGIN_METADATA:
1423+
metadata = PLUGIN_METADATA[plugin]
1424+
if platform_name in metadata.platforms:
1425+
default_plugins.append(plugin)
14221426

14231427
return sorted(default_plugins)
14241428

docs/CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,21 @@
77
## Currently implemented plug-ins
88
- `visualizer`
99
- `radiation`
10-
- `weber-penn tree`
10+
- `weber-penn tree`
11+
12+
# [v0.0.1] 2025-08-21
13+
14+
## Helios native C++
15+
Fix helios-core submodule to point to correct remote commit
16+
- Reset submodule to match actual remote state (228a3d389)
17+
- Remove local divergent commits that don't exist on remote
18+
- This fixes the git history display showing non-existent commits
19+
20+
## Context
21+
- Add primitive data operations for all types (float, int, string, vec2/3/4, int2/3/4)
22+
- Add primitive data query functions (exists, type, size)
23+
- Add auto-detection getter and pseudo-color visualization support
24+
- Extend Context.py with comprehensive primitive data methods
25+
- Add robust error handling and cross-platform ctypes wrappers
26+
- Include comprehensive test coverage for all primitive data operations
27+
- Added Context::getPrimitiveDataArray() to return a numpy array of primitive data

docs/Doxyfile.python

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#---------------------------------------------------------------------------
77

88
PROJECT_NAME = "PyHelios"
9-
PROJECT_NUMBER =
9+
PROJECT_NUMBER = 0.0.1
1010
PROJECT_BRIEF =
1111
PROJECT_LOGO = docs/images/PyHelios_logo_whiteborder.png
1212
OUTPUT_DIRECTORY = docs/generated

docs/api_guide.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,93 @@ species = context.getPrimitiveDataString(uuid, "species")
213213
velocity_list = context.getPrimitiveDataVec3(uuid, "velocity") # Returns [x, y, z]
214214
```
215215

216+
#### Getting Multiple Primitive Data Values as Arrays
217+
218+
PyHelios provides `getPrimitiveDataArray()` for efficiently retrieving primitive data from multiple primitives:
219+
220+
```python
221+
import numpy as np
222+
223+
# Create multiple primitives and set data
224+
patch_uuids = []
225+
for i in range(10):
226+
uuid = context.addPatch(center=vec3(i, 0, 0))
227+
context.setPrimitiveDataFloat(uuid, "temperature", 20.0 + i * 2.5)
228+
context.setPrimitiveDataInt(uuid, "leaf_count", 50 + i * 10)
229+
context.setPrimitiveDataString(uuid, "species", f"species_{i}")
230+
patch_uuids.append(uuid)
231+
232+
# Get data arrays - automatically determines appropriate NumPy dtype
233+
temperatures = context.getPrimitiveDataArray(patch_uuids, "temperature")
234+
# Returns: numpy.ndarray with dtype=float32, shape=(10,)
235+
# Values: [20.0, 22.5, 25.0, 27.5, 30.0, 32.5, 35.0, 37.5, 40.0, 42.5]
236+
237+
leaf_counts = context.getPrimitiveDataArray(patch_uuids, "leaf_count")
238+
# Returns: numpy.ndarray with dtype=int32, shape=(10,)
239+
# Values: [50, 60, 70, 80, 90, 100, 110, 120, 130, 140]
240+
241+
species_names = context.getPrimitiveDataArray(patch_uuids, "species")
242+
# Returns: numpy.ndarray with dtype=object, shape=(10,)
243+
# Values: ['species_0', 'species_1', ..., 'species_9']
244+
245+
# Works with any primitive type and data type
246+
triangle_uuids = [
247+
context.addTriangle(vec3(0,0,0), vec3(1,0,0), vec3(0.5,1,0)),
248+
context.addTriangle(vec3(2,0,0), vec3(3,0,0), vec3(2.5,1,0))
249+
]
250+
for i, uuid in enumerate(triangle_uuids):
251+
context.setPrimitiveDataFloat(uuid, "area", (i + 1) * 0.5)
252+
253+
areas = context.getPrimitiveDataArray(triangle_uuids, "area")
254+
# Returns: numpy.ndarray with dtype=float32, shape=(2,)
255+
# Values: [0.5, 1.0]
256+
257+
# Vector data returns 2D arrays
258+
for i, uuid in enumerate(patch_uuids[:3]):
259+
context.setPrimitiveDataFloat(uuid, "velocity_x", float(i))
260+
context.setPrimitiveDataFloat(uuid, "velocity_y", float(i + 10))
261+
context.setPrimitiveDataFloat(uuid, "velocity_z", float(i + 20))
262+
263+
velocities_x = context.getPrimitiveDataArray(patch_uuids[:3], "velocity_x")
264+
velocities_y = context.getPrimitiveDataArray(patch_uuids[:3], "velocity_y")
265+
velocities_z = context.getPrimitiveDataArray(patch_uuids[:3], "velocity_z")
266+
# Each returns: numpy.ndarray with dtype=float32, shape=(3,)
267+
268+
# Combine into velocity vectors if needed
269+
velocities = np.column_stack([velocities_x, velocities_y, velocities_z])
270+
# Shape: (3, 3) - 3 primitives, each with 3D velocity
271+
```
272+
273+
**Array Data Types:**
274+
- `int` data → `numpy.int32` array
275+
- `uint` data → `numpy.uint32` array
276+
- `float` data → `numpy.float32` array
277+
- `double` data → `numpy.float64` array
278+
- `string` data → `numpy.object` array
279+
- `vec2/vec3/vec4` data → `numpy.float32` array with shape `(N, vector_size)`
280+
- `int2/int3/int4` data → `numpy.int32` array with shape `(N, vector_size)`
281+
282+
**Error Handling:**
283+
```python
284+
# Empty UUID list
285+
try:
286+
data = context.getPrimitiveDataArray([], "temperature")
287+
except ValueError as e:
288+
print("Error:", e) # "UUID list cannot be empty"
289+
290+
# Invalid UUID
291+
try:
292+
data = context.getPrimitiveDataArray([999999], "temperature")
293+
except ValueError as e:
294+
print("Error:", e) # "Primitive data 'temperature' does not exist for UUID 999999"
295+
296+
# Non-existent data label
297+
try:
298+
data = context.getPrimitiveDataArray(patch_uuids, "nonexistent_label")
299+
except ValueError as e:
300+
print("Error:", e) # "Primitive data 'nonexistent_label' does not exist for UUID <uuid>"
301+
```
302+
216303
### Actual File Operations
217304

218305
These methods are verified from the wrapper implementation:

helios-core

0 commit comments

Comments
 (0)