Skip to content

Commit 4e2564d

Browse files
committed
[v0.1.3] 2025-09-22
🚨++ New Plug-in Integrated ++ 🚨 - Initial phase of plant architecture plug-in integrated with PyHelios. This includes basic functionality for building plants from the library. - Updated Helios native C++ library to v1.3.50 *Improved Error Handling, Build System Optimization, and Testing Infrastructure* - **Context API**: Enhanced lifecycle state tracking with detailed error messages for better debugging - **Build System**: Streamlined asset management by removing redundant asset copying code and optimizing build process - **Testing**: Enhanced cross-platform test coverage with improved mock mode handling and context lifecycle testing - **Documentation**: Major updates to plugin integration guide with critical implementation patterns and best practices - **Visualizer**: Enhanced compatibility and error handling for cross-platform visualization workflows - Removed redundant asset copying for visualizer and weberpenntree plugins (using environment variable approach) - Optimized build process with cleaner CMake integration - Enhanced cross-platform library validation with fail-fast behavior
1 parent 2f26caa commit 4e2564d

26 files changed

Lines changed: 2724 additions & 341 deletions

β€Ž.github/workflows/build-wheels.ymlβ€Ž

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ name: Build Wheels
22

33
on:
44
push:
5-
tags: ['v*']
5+
tags: ['v*','testing-v*']
6+
branches: [master]
67
workflow_dispatch:
78

89
jobs:
@@ -335,8 +336,8 @@ jobs:
335336
# Test Linux testable plugins including headless visualizer
336337
# Only GPU-accelerated plugins require special hardware not available in CI
337338
available_plugins = info.get('available_plugins', [])
338-
testable_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance']
339-
built_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'energybalance', 'radiation']
339+
testable_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'plantarchitecture']
340+
built_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'energybalance', 'radiation', 'plantarchitecture']
340341
341342
print(f'[INFO] Available plugins: {sorted(available_plugins)}')
342343
print(f'[INFO] Built plugins (expected): {sorted(built_plugins)}')
@@ -431,9 +432,9 @@ jobs:
431432
lib_path = info.get('library_path', 'Unknown')
432433
print(f'[SUCCESS] Native library loaded: {lib_path}')
433434
434-
# Test macOS expected plugins (5 plugins including visualization but no GPU)
435+
# Test macOS expected plugins (6 plugins including visualization but no GPU)
435436
available_plugins = info.get('available_plugins', [])
436-
expected_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance']
437+
expected_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'plantarchitecture']
437438
print(f'[INFO] Available plugins: {sorted(available_plugins)}')
438439
print(f'[INFO] Expected plugins: {sorted(expected_plugins)}')
439440
@@ -524,8 +525,8 @@ jobs:
524525
# Test Windows testable plugins (CI containers don't have GPU for radiation/energybalance testing)
525526
# We build GPU plugins but can't test them in CI environment
526527
available_plugins = info.get('available_plugins', [])
527-
testable_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance']
528-
built_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'energybalance', 'radiation']
528+
testable_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'plantarchitecture']
529+
built_plugins = ['weberpenntree', 'visualizer', 'photosynthesis', 'solarposition', 'stomatalconductance', 'energybalance', 'radiation', 'plantarchitecture']
529530
530531
print(f'[INFO] Available plugins: {sorted(available_plugins)}')
531532
print(f'[INFO] Built plugins (expected): {sorted(built_plugins)}')

β€Ž.github/workflows/pytest-linux-gpu.yamlβ€Ž

Lines changed: 0 additions & 94 deletions
This file was deleted.

β€ŽREADME.mdβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<br><br>
22

3-
[![Build Wheels](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/build-wheels.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/build-wheels.yml) [![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)
3+
[![Build Wheels](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/build-wheels.yml/badge.svg?event=push)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/build-wheels.yml) [![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)
44

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

β€Žbuild_scripts/build_helios.pyβ€Ž

Lines changed: 6 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,15 +1269,7 @@ def copy_to_output(self, library_path: Path) -> Path:
12691269

12701270
# Validate that the copied library can be loaded by ctypes (FAIL-FAST validation)
12711271
self._validate_library_loadable(output_path)
1272-
1273-
# NOTE: Asset copying for visualizer plugin disabled - Stage 1 asset management
1274-
# uses environment variables to reference assets directly from helios-core source
1275-
# self._copy_visualizer_assets()
1276-
1277-
# NOTE: Asset copying for weberpenntree plugin disabled - Stage 1 asset management
1278-
# uses environment variables to reference assets directly from helios-core source
1279-
# self._copy_weberpenntree_assets()
1280-
1272+
12811273
# Also copy any additional required files
12821274
if self.platform_name == 'Windows':
12831275
# Look for PDB files for debugging
@@ -1287,95 +1279,7 @@ def copy_to_output(self, library_path: Path) -> Path:
12871279
print(f"Copied debug symbols: {pdb_path}")
12881280

12891281
return output_path
1290-
1291-
def _copy_visualizer_assets(self) -> None:
1292-
"""
1293-
Copy all visualizer assets (shaders, textures, fonts) to the expected location.
1294-
1295-
The C++ Visualizer code expects assets at "plugins/visualizer/" relative to the
1296-
working directory. This method copies all assets from the build directory to
1297-
the PyHelios directory structure where they can be found at runtime.
1298-
1299-
Assets copied:
1300-
- Shader files (.vert, .frag)
1301-
- Texture files
1302-
- Font files
1303-
"""
1304-
# Base paths
1305-
build_visualizer_dir = self.build_dir / 'plugins' / 'visualizer'
1306-
target_base_dir = self.output_dir.parent / 'plugins' / 'visualizer'
1307-
1308-
if not build_visualizer_dir.exists():
1309-
print(f"[INFO] Visualizer assets directory not found: {build_visualizer_dir} (visualizer plugin may not be enabled)")
1310-
return
1311-
1312-
total_files_copied = 0
1313-
1314-
# Copy shader files
1315-
build_shader_dir = build_visualizer_dir / 'shaders'
1316-
if build_shader_dir.exists():
1317-
target_shader_dir = target_base_dir / 'shaders'
1318-
target_shader_dir.mkdir(parents=True, exist_ok=True)
1319-
1320-
shader_count = 0
1321-
for shader_file in build_shader_dir.glob('*'):
1322-
if shader_file.is_file():
1323-
dest_file = target_shader_dir / shader_file.name
1324-
shutil.copy2(shader_file, dest_file)
1325-
shader_count += 1
1326-
print(f"Copied shader: {shader_file.name}")
1327-
1328-
total_files_copied += shader_count
1329-
if shader_count > 0:
1330-
print(f"[OK] Copied {shader_count} shader files")
1331-
1332-
# Copy texture files
1333-
build_texture_dir = build_visualizer_dir / 'textures'
1334-
if build_texture_dir.exists():
1335-
target_texture_dir = target_base_dir / 'textures'
1336-
target_texture_dir.mkdir(parents=True, exist_ok=True)
1337-
1338-
texture_count = 0
1339-
for texture_file in build_texture_dir.rglob('*'):
1340-
if texture_file.is_file():
1341-
# Preserve directory structure for textures
1342-
rel_path = texture_file.relative_to(build_texture_dir)
1343-
dest_file = target_texture_dir / rel_path
1344-
dest_file.parent.mkdir(parents=True, exist_ok=True)
1345-
shutil.copy2(texture_file, dest_file)
1346-
texture_count += 1
1347-
print(f"Copied texture: {rel_path}")
1348-
1349-
total_files_copied += texture_count
1350-
if texture_count > 0:
1351-
print(f"[OK] Copied {texture_count} texture files")
1352-
1353-
# Copy font files
1354-
build_font_dir = build_visualizer_dir / 'fonts'
1355-
if build_font_dir.exists():
1356-
target_font_dir = target_base_dir / 'fonts'
1357-
target_font_dir.mkdir(parents=True, exist_ok=True)
1358-
1359-
font_count = 0
1360-
for font_file in build_font_dir.rglob('*'):
1361-
if font_file.is_file():
1362-
# Preserve directory structure for fonts
1363-
rel_path = font_file.relative_to(build_font_dir)
1364-
dest_file = target_font_dir / rel_path
1365-
dest_file.parent.mkdir(parents=True, exist_ok=True)
1366-
shutil.copy2(font_file, dest_file)
1367-
font_count += 1
1368-
print(f"Copied font: {rel_path}")
1369-
1370-
total_files_copied += font_count
1371-
if font_count > 0:
1372-
print(f"[OK] Copied {font_count} font files")
1373-
1374-
if total_files_copied > 0:
1375-
print(f"[OK] Successfully copied {total_files_copied} visualizer assets to {target_base_dir}")
1376-
else:
1377-
print(f"[WARN] No visualizer assets found to copy")
1378-
1282+
13791283
def _clean_duplicate_symbols(self, main_lib_path: Path, build_lib_dir: Path) -> Dict[str, Any]:
13801284
"""
13811285
Clean duplicate symbols from static libraries by removing test objects.
@@ -1710,20 +1614,21 @@ def _patch_zlib_cmake_for_windows(self) -> None:
17101614
def get_default_plugins() -> List[str]:
17111615
"""
17121616
Get the default set of plugins (only the currently integrated plugins).
1713-
1617+
17141618
Currently integrated plugins in PyHelios:
17151619
- visualizer: OpenGL-based 3D visualization
17161620
- weberpenntree: Procedural tree generation
17171621
- radiation: OptiX-accelerated ray tracing (GPU optional)
17181622
- energybalance: GPU-accelerated thermal modeling and energy balance
17191623
- solarposition: Solar position calculations and sun angle modeling
17201624
- photosynthesis: Photosynthesis modeling and carbon assimilation
1721-
1625+
- plantarchitecture: Advanced plant structure and architecture modeling with procedural plant library
1626+
17221627
Returns:
17231628
List of default plugins
17241629
"""
17251630
# Return the plugins that are actually integrated into PyHelios
1726-
integrated_plugins = ["visualizer", "weberpenntree", "radiation", "energybalance", "solarposition", "stomatalconductance", "photosynthesis"]
1631+
integrated_plugins = ["visualizer", "weberpenntree", "radiation", "energybalance", "solarposition", "stomatalconductance", "photosynthesis", "plantarchitecture"]
17271632

17281633
# Filter by platform compatibility
17291634
default_plugins = []

β€Ždocs/CHANGELOG.mdβ€Ž

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

3+
# [v0.1.3] 2025-09-22
4+
5+
🚨++ New Plug-in Integrated ++ 🚨
6+
- Initial phase of plant architecture plug-in integrated with PyHelios. This includes basic functionality for building plants from the library.
7+
8+
- Updated Helios native C++ library to v1.3.50
9+
10+
*Improved Error Handling, Build System Optimization, and Testing Infrastructure*
11+
- **Context API**: Enhanced lifecycle state tracking with detailed error messages for better debugging
12+
- **Build System**: Streamlined asset management by removing redundant asset copying code and optimizing build process
13+
- **Testing**: Enhanced cross-platform test coverage with improved mock mode handling and context lifecycle testing
14+
- **Documentation**: Major updates to plugin integration guide with critical implementation patterns and best practices
15+
- **Visualizer**: Enhanced compatibility and error handling for cross-platform visualization workflows
16+
17+
## Build System
18+
- Removed redundant asset copying for visualizer and weberpenntree plugins (using environment variable approach)
19+
- Optimized build process with cleaner CMake integration
20+
- Enhanced cross-platform library validation with fail-fast behavior
21+
322
# [v0.1.2] 2025-09-18
423

524
πŸŽ‰PyPI package distribution should now be working for all integrated plug-ins πŸŽ‰

β€Ždocs/Doxyfile.pythonβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ INPUT = pyhelios \
131131
docs/plugin_integration_guide.md \
132132
docs/plugin_energybalance.md \
133133
docs/plugin_photosynthesis.md \
134+
docs/plugin_plantarchitecture.md \
134135
docs/plugin_radiation.md \
135136
docs/plugin_solarposition.md \
136137
docs/plugin_stomatalconductance.md \
@@ -149,6 +150,7 @@ EXCLUDE = pyhelios/plugins/__pycache__ \
149150
pyhelios/wrappers/UContextWrapper.py \
150151
pyhelios/wrappers/UGlobalWrapper.py \
151152
pyhelios/wrappers/ULoggerWrapper.py \
153+
pyhelios/wrappers/UPlantArchitectureWrapper.py \
152154
pyhelios/wrappers/URadiationModelWrapper.py \
153155
pyhelios/wrappers/UEnergyBalanceWrapper.py \
154156
pyhelios/wrappers/UPhotosynthesisWrapper.py \

β€Ždocs/DoxygenLayout.xmlβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<!-- Currently Implemented Plugins (Alphabetized) -->
2626
<tab type="user" visible="yes" url="@ref EnergyBalanceDoc" title="Energy Balance Model"/>
2727
<tab type="user" visible="yes" url="@ref PhotosynthesisDoc" title="Photosynthesis Model"/>
28+
<tab type="user" visible="yes" url="@ref PlantArchitectureDoc" title="Plant Architecture"/>
2829
<tab type="user" visible="yes" url="@ref RadiationDoc" title="Radiation Model"/>
2930
<tab type="user" visible="yes" url="@ref SolarPositionDoc" title="Solar Position"/>
3031
<tab type="user" visible="yes" url="@ref StomatalConductanceDoc" title="Stomatal Conductance Model"/>

0 commit comments

Comments
Β (0)