How velantis-wind/velantiswind works
1. Host environment and main boundary
VelantisWind is a QGIS Python plugin, not a standalone app. The architectural boundary is the QGIS host: plugin code reads project layers, launches Qt dialogs/panels, runs domain calculations in-process, and writes results back into QGIS layers, rasters, or plugin dialogs.
2. Top-level plugin entry and feature navigation
plugin.py is the integration point that exposes the plugin to QGIS. From there, the user is routed into three major workflows: Energy, Noise, and Shadow. The UI entry files (energy_page.py, noise_page.py, shadow_page.py) and dialogs (*_dialog.py, results dialogs, support/help dialogs) act as presentation shells around the computational cores.
3. Shared UI and compatibility layer
The plugin includes a small shared UI layer: ui_core/responsive.py for layout behavior and qt_compat.py for Qt/QGIS version compatibility. This matters because the repository targets both QGIS 3.x / Qt5 and QGIS 4 / Qt6. UI code is therefore separated from computation so the computational modules can survive Qt migration with minimal change.
4. Energy / AEP subsystem
The energy workflow is split into a higher-level orchestration layer (energy_core) and a deeper analysis engine (ag_core). energy_core handles dialog state, validation, user feedback, and runner control. ag_core contains the actual AEP pipeline: turbine models, wind resource loading, simulation orchestration, physics factories, results building, and QGIS export adapters. The readme notes that the wake-aware energy path depends on PyWake in the QGIS Python environment.
5. Energy data flow
The energy flow is: user inputs and QGIS layers → validation and model setup → resource loading (wrg_reader.py, wrg_site.py, ag_core/orchestration/resource_loader.py) → simulation (ag_core/simulation/runner.py, ag_core/aep_compute.py) → result assembly (ag_core/orchestration/result_builder.py, ag_core/results/*) → export to QGIS or file outputs (ag_core/qgis_io/*, ag_core/export_results.py). This subsystem is the most clearly layered one in the repo.
6. Energy physics and model boundaries
Within ag_core/physics, the calculation engine is split into wake, turbulence, blockage, and rotor_average factories, plus a common/compat.py utility. These factory-style subpackages indicate interchangeable physics implementations behind a common orchestration interface, which is important for diagramming the numerical core as modular rather than monolithic.
7. Noise subsystem
noise_core is a self-contained workflow for early-stage acoustic assessment. It has its own dialog controller/state, validation, runner, task orchestration, result evaluation, and QGIS output adapters. Internally it separates sources, receivers, propagation, acoustics/spectra, and raster/task processing, with both a noise_engine_fast.py and noise_engine_iso.py suggesting alternate calculation paths or standards-based modes.
8. Noise data flow
The noise pipeline is: source and receiver collection from QGIS layers → snapshot/task preparation → propagation and spectral calculations → result payload/summary generation → QGIS layer updates via noise_core/qgis_io/*. The bundled spectrum_library/*.csv files are a key architectural input source, meaning the noise engine relies on packaged turbine spectrum data rather than only external inputs.
9. Shadow flicker subsystem
shadow_core is another independent domain workflow. It collects turbines and receptors, models terrain and solar position, handles timezone logic, and runs calculations via calculation/executor.py and point_runner.py. Like noise, it has a dedicated runner, dialog controller/state, validation, results summary, raster tasking, and QGIS I/O layer.
10. Shadow-specific infrastructure
The shadow module includes solar_geometry.py, terrain/dem.py, and timezone_utils.py, showing that shadow flicker depends on both geographic elevation and time-zone-aware solar timing. The bundled assets/tzdata package is architecturally important here: it gives the plugin a self-contained timezone database so time calculations can be done reliably inside QGIS environments.
11. QGIS integration and output surfaces
Each major module has a QGIS adapter package (ag_core/qgis_io, noise_core/qgis_io, shadow_core/qgis_io) to translate calculation outputs into map layers, raster products, or project objects. This is the main boundary where numerical results become GIS-visible artifacts. Result dialogs (results_dialog.py, noise_results_dialog.py) complement the map outputs for review and validation.
12. Shared data model and validation pattern
Across modules, the repository consistently uses a pattern of domain.py, dialog_state.py, validation.py, runner.py, and ui_feedback.py. That implies a repeated architecture: define a domain model, validate user/project inputs, run the computation, and report status back to the UI. This makes the modules independently testable and easier to diagram as parallel pipelines.
13. External and packaged dependencies
The key runtime dependency that materially affects architecture is QGIS itself, with the plugin running in its embedded Python environment. For energy calculations, PyWake is an external dependency that must be installed into the same environment. The repo also bundles supporting assets like timezone data and wind/noise spectrum files, reducing reliance on system-installed data.
14. Overall architectural shape
The repository is a plugin shell around three domain engines, with shared UI/runtime compatibility at the top and QGIS adapters at the edges. The dominant flow is: QGIS layers and project state in → module-specific validation and computation in the core → QGIS layers, rasters, and result dialogs out. The clearest diagram should show three parallel vertical stacks—Energy, Noise, Shadow—sharing the same host/plugin boundary but using separate numerical and data-handling internals.
Main entry points: hub_dialog.py Hub dialog · responsive.py Responsive UI · dialog_controller.py Energy control · runner.py Simulation run
Components 26
QGIS Host
Plugin runs inside QGIS and exchanges project layers, rasters, and dialogs.
- TZ data · Bundled timezone database used by shadow calculations.
VelantisWind/assets/tzdata
UI Shell
Plugin entry points, shared compatibility, and presentation surfaces.
- Plugin entry · Registers the plugin with QGIS and dispatches major workflows.
VelantisWind/plugin.py - Qt compat · Bridges Qt/QGIS version differences across supported runtimes.
VelantisWind/qt_compat.py - Responsive UI · Shared UI behavior for dialogs and panels.
VelantisWind/ui_core/responsive.py - AEP dialog · Presentation shell for the energy/AEP workflow.
VelantisWind/aep_setup_dialog.py - Hub dialog · Main plugin dialog or landing surface for navigation.
VelantisWind/hub_dialog.py - Noise page · Presentation entry for the noise workflow.
VelantisWind/noise_page.py - Shadow page · Presentation entry for the shadow workflow.
VelantisWind/shadow_page.py
Energy
Wake-aware AEP workflow from input layers to simulation and export.
- Energy control · Validates state, manages runner lifecycle, and feeds UI feedback.
VelantisWind/energy_core/dialog_controller.py - Resource load · Loads project data, site context, and simulation resources for AEP.
VelantisWind/ag_core/orchestration/resource_loader.py - Simulation run · Executes energy calculations and orchestrates the AEP compute pipeline.
VelantisWind/ag_core/simulation/runner.py - Physics core · Wake, turbulence, blockage, and rotor-average factories behind the energy engine.
VelantisWind/ag_core/physics - Energy results · Builds arrays, tables, summaries, and export-ready outputs.
VelantisWind/ag_core/orchestration/result_builder.py - Energy I/O · Writes AEP outputs back into layers and project artifacts.
VelantisWind/ag_core/qgis_io
Noise
Acoustic assessment workflow with alternate engine paths and GIS outputs.
- Noise control · Coordinates validation, task execution, and result feedback for noise runs.
VelantisWind/noise_core/dialog_controller.py - Inputs collect · Collects noise sources and receivers from QGIS layers.
VelantisWind/noise_core/sources/collector.py - Noise task · Prepares snapshots and executes the acoustic computation path.
VelantisWind/noise_core/tasks/noise_task.py - Propagation · Handles ground effects, spectra, and alternate fast/ISO engine modes.
VelantisWind/noise_core/propagation - Noise results · Evaluates and summarizes acoustic outputs for review.
VelantisWind/noise_core/results - Noise I/O · Applies noise results to project layers and GIS outputs.
VelantisWind/noise_core/qgis_io
Shadow
Shadow flicker workflow with terrain and timezone-aware calculation.
- Shadow control · Coordinates validation, runner control, and feedback for shadow flicker runs.
VelantisWind/shadow_core/dialog_controller.py - Shadow inputs · Collects turbines and receptors for shadow analysis.
VelantisWind/shadow_core/turbines/collector.py - Shadow calc · Runs point-based and batch shadow flicker calculations.
VelantisWind/shadow_core/calculation/executor.py - Terrain/time · Provides solar geometry, DEM terrain, and timezone logic for shading timing.
VelantisWind/shadow_core/solar_geometry.py - Shadow results · Summarizes flicker outputs for UI review.
VelantisWind/shadow_core/results/summary.py - Shadow I/O · Publishes shadow outputs into layers and raster/map products.
VelantisWind/shadow_core/qgis_io
Connections 28
- Plugin entry → Hub dialog: opens · Routes users into the main plugin surface.
- Hub dialog → AEP dialog: launches · Opens the energy workflow shell.
- Hub dialog → Noise page: launches · Opens the noise workflow shell.
- Hub dialog → Shadow page: launches · Opens the shadow workflow shell.
- Qt compat → Plugin entry: supports · Keeps plugin UI code compatible across Qt/QGIS versions.
- Responsive UI → AEP dialog: supports · Shared layout behavior for workflow pages and dialogs.
- Responsive UI → Noise page: supports · Shared layout behavior for workflow pages and dialogs.
- Responsive UI → Shadow page: supports · Shared layout behavior for workflow pages and dialogs.
- AEP dialog → Energy control: drives · Presentation layer hands state and actions to the controller.
- Energy control → Resource load: loads · Builds simulation context from QGIS project inputs.
- Resource load → Simulation run: configures · Feeds the AEP simulation runner.
- Simulation run → Physics core: uses · Computes wake-aware energy using modular physics implementations.
- Simulation run → Energy results: emits · Passes computed arrays and intermediate outputs for assembly.
- Energy results → Energy I/O: exports · Sends final energy products to QGIS adapters.
- Energy control → Energy I/O: reports · Surfaces outputs and status to the host environment.
- Noise page → Noise control: drives · Presentation layer hands state and actions to the controller.
- Noise control → Inputs collect: collects · Builds the noise input set from project layers.
- Inputs collect → Noise task: prepares · Creates task-ready source and receiver inputs.
- Noise task → Propagation: computes · Runs acoustic propagation and spectral calculations.
- Propagation → Noise results: produces · Outputs payloads for evaluation and summaries.
- Noise results → Noise I/O: exports · Applies noise results back into QGIS.
- Shadow page → Shadow control: drives · Presentation layer hands state and actions to the controller.
- Shadow control → Shadow inputs: collects · Builds the shadow input set from project layers.
- Shadow inputs → Shadow calc: prepares · Creates calculation-ready turbine and receptor inputs.
- Shadow calc → Terrain/time: depends on · Uses terrain, solar geometry, and timezone-aware timing.
- Shadow calc → Shadow results: produces · Generates flicker outputs for summarization.
- Shadow results → Shadow I/O: exports · Publishes shadow products to QGIS.
- Terrain/time → TZ data: reads · Uses packaged timezone data for local-time calculations.