Skip to content

Commit 1e792b4

Browse files
committed
Refactor test methods and add RadiationModel support
Refactored test suite to align with updated method naming conventions in Helios (e.g., camelCase). Added a new RadiationModel module with Python bindings for radiation transport simulation, alongside supporting ctypes wrappers and CMake configurations for the radiation plugin. This extends functionality to handle radiative transfer models leveraging CUDA/OptiX.
1 parent ee00276 commit 1e792b4

21 files changed

Lines changed: 1013 additions & 139 deletions

.github/workflows/test-linux.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ jobs:
2323
with:
2424
python-version: ${{ matrix.python-version }}
2525

26-
- name: Install system dependencies
26+
- name: Install dependencies using Helios script
2727
run: |
28-
sudo apt-get update
29-
sudo apt-get install -y build-essential cmake
28+
cd helios-core
29+
chmod +x utilities/dependencies.sh
30+
# Install BASE dependencies (includes build-essential, cmake)
31+
bash utilities/dependencies.sh BASE
3032
3133
- name: Install Python dependencies
3234
run: |

.github/workflows/test-macos.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ jobs:
2323
with:
2424
python-version: ${{ matrix.python-version }}
2525

26-
- name: Install system dependencies
26+
- name: Install dependencies using Helios script
2727
run: |
28-
# Install Xcode command line tools (usually pre-installed on GitHub runners)
29-
# xcode-select --install
30-
brew install cmake
28+
cd helios-core
29+
chmod +x utilities/dependencies.sh
30+
# Install BASE dependencies (includes cmake and build tools)
31+
bash utilities/dependencies.sh BASE
3132
3233
- name: Install Python dependencies
3334
run: |

.github/workflows/test-matrix.yml

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,13 @@ jobs:
2727
with:
2828
python-version: ${{ matrix.python-version }}
2929

30-
- name: Install system dependencies (Linux)
31-
if: matrix.os == 'ubuntu-latest'
30+
- name: Install dependencies using Helios script (Linux/macOS)
31+
if: matrix.os != 'windows-latest'
3232
run: |
33-
sudo apt-get update
34-
sudo apt-get install -y build-essential cmake
35-
36-
- name: Install system dependencies (macOS)
37-
if: matrix.os == 'macos-latest'
38-
run: |
39-
brew install cmake
33+
cd helios-core
34+
chmod +x utilities/dependencies.sh
35+
# Install BASE dependencies (GCC, G++, CMake) for matrix testing
36+
bash utilities/dependencies.sh BASE
4037
4138
- name: Set up MSVC (Windows)
4239
if: matrix.os == 'windows-latest'
@@ -202,16 +199,13 @@ jobs:
202199
with:
203200
python-version: "3.11"
204201

205-
- name: Install system dependencies (Linux)
206-
if: matrix.os == 'ubuntu-latest'
207-
run: |
208-
sudo apt-get update
209-
sudo apt-get install -y build-essential cmake
210-
211-
- name: Install system dependencies (macOS)
212-
if: matrix.os == 'macos-latest'
202+
- name: Install dependencies using Helios script (Linux/macOS)
203+
if: matrix.os != 'windows-latest'
213204
run: |
214-
brew install cmake
205+
cd helios-core
206+
chmod +x utilities/dependencies.sh
207+
# Install BASE dependencies for build script testing
208+
bash utilities/dependencies.sh BASE
215209
216210
- name: Set up MSVC (Windows)
217211
if: matrix.os == 'windows-latest'

.github/workflows/test-native.yml

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,25 @@ jobs:
3434
with:
3535
python-version: "3.11"
3636

37-
- name: Install system dependencies (Linux)
38-
if: matrix.os == 'ubuntu-latest'
37+
- name: Install dependencies using Helios script (Linux/macOS)
38+
if: matrix.os != 'windows-latest'
3939
run: |
40-
sudo apt-get update
41-
sudo apt-get install -y build-essential cmake libx11-dev xorg-dev libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev
42-
43-
- name: Install system dependencies (macOS)
44-
if: matrix.os == 'macos-latest'
45-
run: |
46-
brew install cmake
40+
cd helios-core
41+
chmod +x utilities/dependencies.sh
42+
# Install VIS dependencies (includes base + OpenGL/X11 for visualization)
43+
bash utilities/dependencies.sh VIS
4744
4845
- name: Set up MSVC (Windows)
4946
if: matrix.os == 'windows-latest'
5047
uses: ilammy/msvc-dev-cmd@v1
5148

49+
- name: Install basic dependencies (Windows)
50+
if: matrix.os == 'windows-latest'
51+
run: |
52+
# Note: dependencies.sh doesn't handle Windows package installation
53+
# but provides guidance. MSVC is already set up above.
54+
echo "Windows dependencies: Visual Studio (MSVC) is already configured"
55+
5256
- name: Install Python dependencies
5357
run: |
5458
python -m pip install --upgrade pip
@@ -97,17 +101,17 @@ jobs:
97101
from pyhelios import Context, DataTypes
98102
with Context() as ctx:
99103
print(f'Context created successfully')
100-
count = ctx.get_primitive_count()
104+
count = ctx.getPrimitiveCount()
101105
print(f'Initial primitive count: {count}')
102106
103107
# Test adding a patch
104-
center = DataTypes.Vec3(1, 2, 3)
105-
size = DataTypes.Vec2(1, 1)
108+
center = DataTypes.vec3(1, 2, 3)
109+
size = DataTypes.vec2(1, 1)
106110
color = DataTypes.RGBcolor(0.5, 0.5, 0.5)
107-
patch_id = ctx.add_patch(center=center, size=size, color=color)
111+
patch_id = ctx.addPatch(center=center, size=size, color=color)
108112
print(f'Added patch with ID: {patch_id}')
109113
110-
new_count = ctx.get_primitive_count()
114+
new_count = ctx.getPrimitiveCount()
111115
print(f'New primitive count: {new_count}')
112116
assert new_count == count + 1, f'Expected {count + 1}, got {new_count}'
113117
@@ -136,10 +140,10 @@ jobs:
136140
print('Testing WeberPennTree with native libraries...')
137141
with Context() as ctx:
138142
with WeberPennTree(ctx) as wpt:
139-
tree_id = wpt.build_tree(WPTType.LEMON)
143+
tree_id = wpt.buildTree(WPTType.LEMON)
140144
print(f'✓ Built tree with ID: {tree_id}')
141145
142-
trunk_uuids = wpt.get_trunk_uuids(tree_id)
146+
trunk_uuids = wpt.getTrunkUUIDs(tree_id)
143147
print(f'✓ Tree has {len(trunk_uuids)} trunk segments')
144148
else:
145149
print('ERROR: Native libraries not available for WeberPennTree testing')

.github/workflows/test-quick.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
print('✓ Context created (mock mode)')
5252
5353
# This should work in mock mode
54-
count = ctx.get_primitive_count()
54+
count = ctx.getPrimitiveCount()
5555
print(f'✓ Primitive count: {count}')
5656
5757
except RuntimeError as e:
@@ -61,7 +61,7 @@ jobs:
6161
raise
6262
6363
print('Testing DataTypes...')
64-
v = DataTypes.Vec3(1.0, 2.0, 3.0)
64+
v = DataTypes.vec3(1.0, 2.0, 3.0)
6565
print(f'✓ Vec3 created: {v}')
6666
6767
c = DataTypes.RGBcolor(0.5, 0.7, 0.2)

.github/workflows/test-required.yml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
print('✓ Context created successfully')
6262
6363
# Test DataTypes
64-
v = DataTypes.Vec3(1.0, 2.0, 3.0)
64+
v = DataTypes.vec3(1.0, 2.0, 3.0)
6565
print(f'✓ Vec3 created: ({v.x}, {v.y}, {v.z})')
6666
6767
c = DataTypes.RGBcolor(0.5, 0.7, 0.2)
@@ -93,21 +93,23 @@ jobs:
9393
with:
9494
python-version: "3.11"
9595

96-
- name: Install system dependencies (Linux)
97-
if: matrix.os == 'ubuntu-latest'
96+
- name: Install dependencies using Helios script (Linux/macOS)
97+
if: matrix.os != 'windows-latest'
9898
run: |
99-
sudo apt-get update
100-
sudo apt-get install -y build-essential cmake libx11-dev xorg-dev libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev
101-
102-
- name: Install system dependencies (macOS)
103-
if: matrix.os == 'macos-latest'
104-
run: |
105-
brew install cmake
99+
cd helios-core
100+
chmod +x utilities/dependencies.sh
101+
# Install VIS dependencies (includes base + OpenGL/X11 for visualization)
102+
bash utilities/dependencies.sh VIS
106103
107104
- name: Set up MSVC (Windows)
108105
if: matrix.os == 'windows-latest'
109106
uses: ilammy/msvc-dev-cmd@v1
110107

108+
- name: Install basic dependencies (Windows)
109+
if: matrix.os == 'windows-latest'
110+
run: |
111+
echo "Windows dependencies: Visual Studio (MSVC) is already configured"
112+
111113
- name: Install Python dependencies
112114
run: |
113115
python -m pip install --upgrade pip

README.md

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,11 @@ PyHelios now works across multiple platforms:
1919
-**Windows** (x64) - Full native support
2020
-**macOS** (Intel/Apple Silicon) - Native support with build-from-source
2121
-**Linux** (x64) - Native support with build-from-source
22-
-**Development Mode** - Mock mode for development on any platform
22+
-**Development Mode** - Explicit mock mode for development without native libraries
2323

2424
## Installation
2525

26-
### Quick Start (Development/Mock Mode)
27-
28-
For immediate use without native libraries (mock mode):
29-
30-
```bash
31-
# Clone repository with Helios core
32-
git clone --recursive git@github.com:PlantSimulationLab/PyHelios.git
33-
cd PyHelios/
34-
35-
# Install in development mode
36-
pip install -e .[dev]
37-
```
38-
39-
### Full Installation with Native Libraries
26+
### Full Installation with Native Helios Libraries
4027

4128
#### Windows
4229
```bash
@@ -115,9 +102,9 @@ tree_id_lemon = wpt.buildTree(WPTType.LEMON)
115102
tree_id_olive = wpt.buildTree(WPTType.OLIVE)
116103
```
117104

118-
## Platform Status and Mock Mode
105+
## Platform Status and Library Requirements
119106

120-
PyHelios automatically detects available native libraries and gracefully falls back to mock mode when they're not available:
107+
PyHelios detects available native libraries and provides clear feedback about the current status:
121108

122109
```python
123110
from pyhelios.plugins import print_plugin_status
@@ -131,7 +118,7 @@ print_plugin_status()
131118
# Mock mode: True
132119
```
133120

134-
In mock mode, PyHelios provides full API compatibility but operations will raise informative errors explaining that native libraries are required for full functionality.
121+
**Important**: PyHelios follows a fail-fast philosophy. When native libraries are not available, operations will raise explicit `RuntimeError` exceptions with clear, actionable error messages explaining what failed and how to fix it. Mock mode is only used during development and testing - it does not silently provide fallback functionality.
135122

136123
## Development and Testing
137124

@@ -163,9 +150,10 @@ python build_scripts/build_helios.py --cmake-args -DCMAKE_BUILD_TYPE=Debug --ver
163150

164151
## Troubleshooting
165152

166-
### Mock Mode Issues
167-
- **Problem**: All operations raise "mock mode" errors
153+
### Native Library Requirements
154+
- **Problem**: Operations raise "mock mode" or "native library required" errors
168155
- **Solution**: Build and install native libraries using `python build_scripts/build_helios.py`
156+
- **Note**: PyHelios requires native libraries for full functionality - mock mode is only for development/testing
169157

170158
### Build Issues
171159
- **Windows**: Ensure Visual Studio or Build Tools are installed

build_scripts/build_helios.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ def check_prerequisites(self) -> None:
101101
except (subprocess.CalledProcessError, FileNotFoundError):
102102
raise HeliosBuildError("No suitable compiler found (gcc or clang)")
103103

104-
# Check that helios-core directory exists and has the new build structure
105-
pyhelios_cmake = self.helios_root / 'pyhelios_build' / 'CMakeLists.txt'
104+
# Check that pyhelios_build directory exists in the main repo
105+
pyhelios_build_dir = self.helios_root.parent / 'pyhelios_build'
106+
pyhelios_cmake = pyhelios_build_dir / 'CMakeLists.txt'
106107
if not pyhelios_cmake.exists():
107108
raise HeliosBuildError(f"PyHelios build CMakeLists.txt not found: {pyhelios_cmake}")
108109

@@ -125,7 +126,7 @@ def run_cmake_configure(self, additional_args: Optional[List[str]] = None) -> No
125126
"""Run CMake configuration."""
126127
cmake_cmd = [
127128
'cmake',
128-
str(self.helios_root / 'pyhelios_build'), # Use new PyHelios build project
129+
str(self.helios_root.parent / 'pyhelios_build'), # Use PyHelios build project in main repo
129130
'-G', self.config['generator']
130131
]
131132

@@ -195,16 +196,69 @@ def find_built_library(self) -> Path:
195196
for path in self.build_dir.rglob(lib_name):
196197
print(f"Found built library: {path}")
197198
return path
199+
200+
# If shared library not found, look for static library as fallback
201+
if self.platform_name in ['Darwin', 'Linux']:
202+
static_lib = 'libhelios.a'
203+
static_paths = [
204+
self.build_dir / 'lib' / static_lib,
205+
self.build_dir / static_lib,
206+
]
207+
for path in static_paths:
208+
if path.exists():
209+
print(f"Found static library (will need conversion): {path}")
210+
return path
211+
212+
# Search recursively for static library
213+
for path in self.build_dir.rglob(static_lib):
214+
print(f"Found static library (will need conversion): {path}")
215+
return path
198216

199217
raise HeliosBuildError(f"Built library {lib_name} not found in build directory")
200218

201219
def copy_to_output(self, library_path: Path) -> None:
202220
"""Copy built library to output directory."""
203221
self.output_dir.mkdir(parents=True, exist_ok=True)
204-
output_path = self.output_dir / library_path.name
205222

206-
shutil.copy2(library_path, output_path)
207-
print(f"Copied library to: {output_path}")
223+
# Check if we found a static library but need a shared library
224+
if library_path.name == 'libhelios.a' and self.platform_name in ['Darwin', 'Linux']:
225+
print("Found static library but PyHelios needs shared library for ctypes")
226+
print("Attempting to convert static to shared library...")
227+
228+
# Create shared library from static library
229+
shared_lib_name = self.config['lib_name']
230+
output_path = self.output_dir / shared_lib_name
231+
232+
try:
233+
if self.platform_name == 'Darwin':
234+
# macOS: Use libtool to create shared library
235+
cmd = [
236+
'libtool', '-dynamic', '-o', str(output_path),
237+
str(library_path), '-lc++'
238+
]
239+
else: # Linux
240+
# Linux: Use gcc to create shared library
241+
cmd = [
242+
'gcc', '-shared', '-o', str(output_path),
243+
'-Wl,--whole-archive', str(library_path), '-Wl,--no-whole-archive',
244+
'-lstdc++'
245+
]
246+
247+
subprocess.run(cmd, check=True)
248+
print(f"Successfully converted static to shared library: {output_path}")
249+
250+
except subprocess.CalledProcessError as e:
251+
print(f"Warning: Failed to convert static to shared library: {e}")
252+
# Fall back to copying the static library
253+
output_path = self.output_dir / library_path.name
254+
shutil.copy2(library_path, output_path)
255+
print(f"Copied static library as fallback: {output_path}")
256+
257+
else:
258+
# Normal case: copy the library directly
259+
output_path = self.output_dir / library_path.name
260+
shutil.copy2(library_path, output_path)
261+
print(f"Copied library to: {output_path}")
208262

209263
# Also copy any additional required files
210264
if self.platform_name == 'Windows':
44.2 KB
Loading

helios-core

0 commit comments

Comments
 (0)