The Visualizer plugin provides OpenGL-based 3D visualization and rendering capabilities. This documentation is based on the actual implementation.
Overview
The Visualizer class provides interactive 3D visualization of Helios scenes with real-time rendering, camera controls, and image export capabilities.
Requirements
The visualizer plugin requires:
- OpenGL 3.3 or higher
- GLFW library for window management
- FreeType library for text rendering
- Display/graphics drivers (X11 on Linux, native on Windows/macOS)
Basic Usage
from pyhelios import Context, Visualizer
context = Context()
patch_uuid = context.addPatch(
center=vec3(0, 0, 0),
size=vec2(2, 2),
color=RGBcolor(0.3, 0.7, 0.2)
)
with Visualizer(width=1024, height=768) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.setCameraPosition(
position=vec3(5, 5, 5),
lookAt=vec3(0, 0, 0)
)
visualizer.setBackgroundColor(RGBcolor(0.5, 0.7, 1.0))
visualizer.setLightingModel("phong")
visualizer.plotInteractive()
Visualizer Creation
Basic Initialization
visualizer = Visualizer(
width=800,
height=600,
antialiasing_samples=1,
headless=False
)
visualizer = Visualizer(
width=1920,
height=1080,
antialiasing_samples=8,
headless=False
)
visualizer = Visualizer(
width=1024,
height=768,
antialiasing_samples=1,
headless=True
)
Context Manager Usage
with Visualizer(1024, 768) as visualizer:
pass
Geometry Loading
Building Context Geometry
visualizer.buildContextGeometry(context)
specific_uuids = [patch_uuid, triangle_uuid]
visualizer.buildContextGeometry(context, uuids=specific_uuids)
Progressive Loading
all_uuids = context.getAllUUIDs()
batch_size = 1000
for i in range(0, len(all_uuids), batch_size):
batch_uuids = all_uuids[i:i + batch_size]
visualizer.buildContextGeometry(context, uuids=batch_uuids)
print(f"Loaded batch {i//batch_size + 1}")
Visualization Modes
Interactive Visualization
visualizer.plotInteractive()
Non-Interactive Updates
visualizer.plotUpdate()
for frame in range(100):
visualizer.buildContextGeometry(context)
visualizer.plotUpdate()
visualizer.printWindow(f"frame_{frame:03d}.jpg")
Camera Control
Cartesian Camera Positioning
visualizer.setCameraPosition(
position=vec3(10, 10, 10),
lookAt=vec3(0, 0, 0)
)
visualizer.setCameraPosition(
position=vec3(0, 0, 20),
lookAt=vec3(0, 0, 0)
)
visualizer.setCameraPosition(
position=vec3(20, 0, 5),
lookAt=vec3(0, 0, 5)
)
Spherical Camera Positioning
visualizer.setCameraPositionSpherical(
angle=SphericalCoord(15, 0.785, 1.57),
lookAt=vec3(0, 0, 0)
)
import math
for angle in range(0, 360, 10):
azimuth = math.radians(angle)
visualizer.setCameraPositionSpherical(
angle=SphericalCoord(20, math.pi/4, azimuth),
lookAt=vec3(0, 0, 0)
)
visualizer.plotUpdate()
visualizer.printWindow(f"orbit_{angle:03d}.jpg")
Camera Animation
def animate_camera(visualizer, start_pos, end_pos, frames=30):
for i in range(frames):
t = i / (frames - 1)
current_pos = vec3(
start_pos.x + t * (end_pos.x - start_pos.x),
start_pos.y + t * (end_pos.y - start_pos.y),
start_pos.z + t * (end_pos.z - start_pos.z)
)
visualizer.setCameraPosition(current_pos, vec3(0, 0, 0))
visualizer.plotUpdate()
visualizer.printWindow(f"camera_anim_{i:03d}.jpg")
start = vec3(20, 0, 10)
end = vec3(0, 20, 10)
animate_camera(visualizer, start, end)
Scene Configuration
Background and Lighting
visualizer.setBackgroundColor(RGBcolor(0.2, 0.3, 0.5))
visualizer.setBackgroundColor(RGBcolor(1.0, 1.0, 1.0))
visualizer.setBackgroundColor(RGBcolor(0.0, 0.0, 0.0))
visualizer.setLightDirection(vec3(0.5, 0.5, -1.0))
visualizer.setLightingModel(0)
visualizer.setLightingModel(1)
visualizer.setLightingModel(2)
visualizer.setLightingModel("none")
visualizer.setLightingModel("phong")
visualizer.setLightingModel("phong_shadowed")
Lighting Scenarios
visualizer.setBackgroundColor(RGBcolor(0.5, 0.7, 1.0))
visualizer.setLightDirection(vec3(0.3, 0.3, -0.9))
visualizer.setLightingModel("phong_shadowed")
visualizer.setBackgroundColor(RGBcolor(0.1, 0.1, 0.1))
visualizer.setLightDirection(vec3(0.0, 0.0, -1.0))
visualizer.setLightingModel("phong")
visualizer.setBackgroundColor(RGBcolor(0.9, 0.9, 0.9))
visualizer.setLightDirection(vec3(0.577, 0.577, -0.577))
visualizer.setLightingModel("phong")
Data Visualization
The visualizer can color primitives based on data values, enabling visualization of simulation results, measurements, or other quantitative data.
from pyhelios import Context, Visualizer
context = Context()
patch1 = context.addPatch(center=vec3(0, 0, 0), size=vec2(1, 1))
patch2 = context.addPatch(center=vec3(2, 0, 0), size=vec2(1, 1))
patch3 = context.addPatch(center=vec3(4, 0, 0), size=vec2(1, 1))
context.setPrimitiveDataFloat(patch1, "temperature", 20.5)
context.setPrimitiveDataFloat(patch2, "temperature", 25.0)
context.setPrimitiveDataFloat(patch3, "temperature", 30.2)
context.setPrimitiveDataFloat(patch1, "radiation_flux_SW", 150.0)
context.setPrimitiveDataFloat(patch2, "radiation_flux_SW", 200.0)
context.setPrimitiveDataFloat(patch3, "radiation_flux_SW", 175.5)
with Visualizer(800, 600) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.colorContextPrimitivesByData("temperature")
visualizer.plotUpdate()
visualizer.colorContextPrimitivesByData("radiation_flux_SW")
visualizer.plotUpdate()
visualizer.colorContextPrimitivesByData("temperature", [patch1, patch3])
visualizer.plotUpdate()
Advanced Data Visualization
from pyhelios import Context, RadiationModel, Visualizer
context = Context()
for i in range(10):
for j in range(10):
leaf_uuid = context.addPatch(
center=vec3(i * 0.5, j * 0.5, 2.0),
size=vec2(0.4, 0.4),
color=RGBcolor(0.3, 0.6, 0.2)
)
try:
with RadiationModel(context) as radiation:
radiation.addRadiationBand("PAR")
radiation.addCollimatedRadiationSource(vec3(0, 0, 10), 1000)
radiation.run()
with Visualizer(1024, 768) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.setBackgroundColor([0.1, 0.1, 0.2])
visualizer.colorContextPrimitivesByData("radiation_flux_PAR")
visualizer.setCameraPosition(
position=vec3(8, 8, 8),
lookAt=vec3(2.5, 2.5, 2)
)
visualizer.setLightingModel("none")
visualizer.plotInteractive()
except Exception as e:
print(f"Radiation simulation not available: {e}")
all_uuids = context.getAllUUIDs("patch")
for i, uuid in enumerate(all_uuids):
flux_value = 50 + (i % 20) * 25
context.setPrimitiveDataFloat(uuid, "simulated_flux", flux_value)
with Visualizer(1024, 768) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.colorContextPrimitivesByData("simulated_flux")
visualizer.plotInteractive()
Data Visualization Best Practices
- Set data before visualization: Always use
context.setPrimitiveDataFloat()
before calling colorContextPrimitivesByData()
- Use meaningful data names: Choose descriptive names like
"temperature_celsius"
or "radiation_flux_PAR"
- Consider data ranges: Large value ranges may require colormap configuration (future enhancement)
- Lighting considerations:
- Use
setLightingModel("none")
to show pure data colors
- Use
setLightingModel("phong")
to maintain surface appearance with data coloring
- Selective visualization: Color specific primitives to highlight regions of interest:
high_flux_uuids = [uuid for uuid in all_uuids
if context.getPrimitiveData(uuid, "flux")[0] > threshold]
visualizer.colorContextPrimitivesByData("flux", high_flux_uuids)
Image Export
Basic Image Saving
visualizer.printWindow("scene_view.jpg")
high_res_visualizer = Visualizer(3840, 2160, headless=True)
high_res_visualizer.buildContextGeometry(context)
high_res_visualizer.setCameraPosition([10, 10, 10], [0, 0, 0])
high_res_visualizer.plotUpdate()
high_res_visualizer.printWindow("high_res_scene.jpg")
Batch Image Generation
views = {
"front": ([0, 15, 5], [0, 0, 5]),
"side": ([15, 0, 5], [0, 0, 5]),
"top": ([0, 0, 20], [0, 0, 0]),
"iso": ([10, 10, 10], [0, 0, 0])
}
for view_name, (position, look_at) in views.items():
visualizer.setCameraPosition(vec3(*position), vec3(*look_at))
visualizer.plotUpdate()
visualizer.printWindow(f"scene_{view_name}.jpg")
Window Management
Window Control
visualizer.closeWindow()
visualizer.closeWindow()
Complete Workflow Examples
Tree Visualization
from pyhelios import Context, WeberPennTree, WPTType, Visualizer
context = Context()
wpt = WeberPennTree(context)
tree_id = wpt.buildTree(WPTType.APPLE)
ground_uuid = context.addPatch(
center=vec3(0, 0, 0),
size=vec2(10, 10),
color=RGBcolor(0.4, 0.3, 0.2)
)
try:
with Visualizer(1200, 800, antialiasing_samples=4) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.setCameraPosition(vec3(8, 8, 6), vec3(0, 0, 3))
visualizer.setBackgroundColor(RGBcolor(0.5, 0.7, 1.0))
visualizer.setLightDirection(vec3(0.3, 0.3, -0.9))
visualizer.setLightingModel("phong_shadowed")
visualizer.plotInteractive()
visualizer.printWindow("apple_tree.jpg")
except VisualizerError as e:
print(f"Visualization failed: {e}")
Animation Sequence
with WeberPennTree(context) as wpt:
tree_id = wpt.buildTree(WPTType.LEMON)
try:
with Visualizer(800, 600, headless=True) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.setBackgroundColor(RGBcolor(0.8, 0.9, 1.0))
visualizer.setLightingModel("phong")
for angle in range(0, 360, 5):
import math
radians = math.radians(angle)
radius = 12
x = radius * math.cos(radians)
y = radius * math.sin(radians)
visualizer.setCameraPosition(vec3(x, y, 6), vec3(0, 0, 3))
visualizer.plotUpdate()
visualizer.printWindow(f"animation/frame_{angle:03d}.jpg")
print("Animation sequence complete")
except VisualizerError as e:
print(f"Animation failed: {e}")
Multi-Scene Comparison
tree_types = [WPTType.APPLE, WPTType.LEMON, WPTType.OLIVE]
for i, tree_type in enumerate(tree_types):
context = Context()
wpt = WeberPennTree(context)
tree_id = wpt.buildTree(tree_type)
try:
with Visualizer(600, 600, headless=True) as visualizer:
visualizer.buildContextGeometry(context)
visualizer.setCameraPosition(vec3(6, 6, 6), vec3(0, 0, 3))
visualizer.setBackgroundColor(RGBcolor(1.0, 1.0, 1.0))
visualizer.setLightingModel("phong")
visualizer.plotUpdate()
visualizer.printWindow(f"tree_comparison_{tree_type.name.lower()}.jpg")
except VisualizerError as e:
print(f"Failed to visualize {tree_type.name}: {e}")
Error Handling
try:
visualizer = Visualizer(1024, 768, antialiasing_samples=4)
except VisualizerError as e:
print(f"Visualizer initialization failed: {e}")
import platform
system = platform.system().lower()
if 'linux' in system:
print("Linux: Install X11 dev packages (libx11-dev, xorg-dev)")
print(" sudo apt-get install libx11-dev xorg-dev libgl1-mesa-dev")
elif 'darwin' in system:
print("macOS: Install XQuartz (brew install --cask xquartz)")
elif 'windows' in system:
print("Windows: Update graphics drivers and Visual Studio runtime")
except ValueError as e:
print(f"Invalid parameters: {e}")
Performance Optimization
Optimized Settings
performance_configs = {
"fast": {
"width": 800,
"height": 600,
"antialiasing": 1,
"lighting": "none"
},
"balanced": {
"width": 1024,
"height": 768,
"antialiasing": 4,
"lighting": "phong"
},
"high_quality": {
"width": 1920,
"height": 1080,
"antialiasing": 8,
"lighting": "phong_shadowed"
}
}
config = performance_configs["balanced"]
visualizer = Visualizer(
config["width"],
config["height"],
antialiasing_samples=config["antialiasing"]
)
visualizer.setLightingModel(config["lighting"])
Memory Management
def visualize_large_scene(context, batch_size=1000):
all_uuids = context.getAllUUIDs()
total_primitives = len(all_uuids)
with Visualizer(1024, 768) as visualizer:
for i in range(0, total_primitives, batch_size):
batch_uuids = all_uuids[i:i + batch_size]
visualizer.buildContextGeometry(context, uuids=batch_uuids)
visualizer.plotUpdate()
print(f"Processed {min(i + batch_size, total_primitives)}/{total_primitives} primitives")
Build Requirements
# Build with visualizer plugin
build_scripts/build_helios --plugins visualizer
# Or use profiles that include visualization
build_scripts/build_helios # Default build includes visualizer
build_scripts/build_helios --plugins visualizer # Visualizer-only build
# Check if visualizer is available
python -c "from pyhelios.plugins import get_plugin_registry; print(get_plugin_registry().is_plugin_available('visualizer'))"
Platform-Specific Installation
Linux (Ubuntu/Debian)
sudo apt-get install libx11-dev xorg-dev libgl1-mesa-dev libglu1-mesa-dev
Linux (CentOS/RHEL)
sudo yum install libX11-devel mesa-libGL-devel mesa-libGLU-devel
macOS
brew install --cask xquartz
# OpenGL should be available by default
Windows
- OpenGL drivers provided by graphics card drivers
- Visual Studio runtime may be required
This documentation covers the actual Visualizer implementation in PyHelios, verified against the wrapper code and high-level interface.