VIPR Plugins¶
VIPR uses a modular plugin architecture to extend functionality. Plugins can add new handlers, hooks, filters, and complete workflows.
Built-in Plugins¶
These plugins are included with vipr-core and provide core functionality:
Inference Plugin - 6-step ML inference workflow system
Domain-agnostic design for ML/AI inference
Handler system for pluggable components
Hook and filter system for extensibility
Configuration-driven pipeline
Normalizers Plugin - Data normalization methods
MinMax, Z-Score, and Log normalization
Filter-based architecture for Step 3 of inference workflow
DataSet-aware transformations with error propagation support
API Plugin - FastAPI endpoint generation and data collection
@api decorator for automatic endpoint generation from CLI controllers
DataCollector for structured UI data (tables, diagrams, images, logs)
UUID-based result storage with automatic file extraction
HuggingFace Plugin - HuggingFace model management
Automatic model download from HuggingFace repositories
Support for multiple repositories and models
Configurable storage paths for weights and configs
CLI commands for manual model downloads
Registry Plugin - Component registry system (documentation coming soon)
Data Loader Plugin - Data loading handlers (documentation coming soon)
Domain-Specific Plugins¶
Plugins that extend VIPR for specific scientific domains:
Reflectometry Plugin - Reflectometry analysis
Reflectorch model integration
RefNx physics-based refinement
Specialized data loaders and visualizations
GID Plugin - GIWAXS/GID Bragg peak detection
TIFF and HDF5 loaders
ONNX inference via mlgidDETECT
Structured peak table + detection image outputs
Plugin Management¶
Installing Plugins¶
External plugins can be installed via pip:
# Example: Install the reflectometry plugin
pip install git+https://codebase.helmholtz.cloud/vipr/vipr-reflectorch-plugin.git
Plugins are automatically discovered through Python entry points defined in pyproject.toml. VIPR loads plugins in two stages:
Internal plugins - Built-in plugins from vipr-core (loaded via Cement’s plugin system)
External plugins - Installed packages (loaded via
discover_and_load_external_plugins()during app setup)
This two-stage loading ensures proper initialization order and allows external plugins to extend core functionality.
Listing Installed Plugins¶
# List all installed plugins
vipr plugins list
# Show plugin registry
vipr registry plugins
Plugin Configuration¶
Plugins can be controlled via YAML files (e.g., vipr-plugins.yaml in your working directory):
plugin.my_plugin:
enabled: true
# Plugin-specific configuration
Note: The key plugin.my_plugin matches the entry point name defined in the plugin’s pyproject.toml, not the package name.
Developing Plugins¶
Quick Start¶
For a working example, check out example-plugin.
Naming Convention¶
Recommended package naming: vipr_{plugin_name}
While not technically required, this convention:
Enables automatic discovery filtering: Discovery commands can filter by plugin name
Creates consistency: Entry point name matches package structure
Simplifies component discovery: Pattern matching works automatically
Example:
# pyproject.toml
[project]
name = "vipr-reflectometry" # PyPI package name (with dash)
[project.entry-points."vipr.plugins"]
reflectometry = "vipr_reflectometry:load" # Plugin name → package:load_function
Entry Point Format: plugin_name = "package_name:load_function"
reflectometry- Plugin identifiervipr_reflectometry- Python package to import:load- Function to call for plugin initialization (receivesappparameter)
Understanding Entry Points:
Entry points are Python’s standard plugin discovery mechanism. When a package is installed (via pip), its entry points are registered in the Python environment. This allows applications to automatically discover installed plugins without knowing their names or import paths.
How VIPR uses entry points:
Automatic Plugin Discovery:
# In vipr-core/vipr/main.py entry_points = importlib.metadata.entry_points(group="vipr.plugins") # Finds all packages with [project.entry-points."vipr.plugins"]
VIPR queries Python for all packages that registered under the
"vipr.plugins"group.Load Function Resolution and Execution: The entry point specifies both the package and the load function:
# Entry point: reflectometry = "vipr_reflectometry:load" from vipr_reflectometry import load # Import the load function load(app) # Call it with VIPR app instance
The
:loadpart tells Python which function to call for plugin initialization.Plugin Identifier: The entry point name (
reflectometry) is used in logs, CLI output, and configuration
Why this matters:
No manual registration needed: Installing a plugin via pip automatically makes it available to VIPR
Clean separation: Each plugin is an independent Python package
Standard Python mechanism: Uses Python’s built-in plugin architecture
Important Distinction:
Entry point name “reflectometry” = Plugin identifier for loading/config
Package name “vipr_reflectometry” = Module path used for component filtering
# Plugin filtering uses the PACKAGE name, not entry point name
vipr discovery hooks --plugin reflectometry
# → Matches module paths starting with: vipr_reflectometry.*
Package structure:
vipr_reflectometry/ # Root package (matches entry point)
├── __init__.py
├── reflectorch/
│ ├── model_loader/
│ └── ...
└── shared/
├── data_loader/
└── ...
This naming allows filtering components by plugin:
vipr discovery hooks --plugin reflectometry # Matches vipr_reflectometry.*
See Discovery Plugin documentation for technical details on how plugin filtering works.
Full Plugin Development Guide¶
See Developing Plugins for a step-by-step guide on creating your own plugins.
Plugin Architecture¶
VIPR plugins can:
Register handlers for component interfaces (data loaders, model loaders, etc.)
Register hooks for event-driven callbacks
Register filters for data transformation
Define CLI controllers for command-line interface
Provide configuration schemas for validation
For technical details, see the architecture documentation (coming soon).