Handler Implementation Patterns

See also

Related Documentation:

This document details how the Reflectometry Plugin implements VIPR handler interfaces for data loading, model loading, and prediction.

DataLoader Handlers

CSV/DAT/TXT DataLoader

Handler: vipr-reflectometry:vipr_reflectometry.shared.data_loader.csv_spectrareader_data_loader.CSVSpectraReaderDataLoader
Label: csv_spectrareader
Interface: vipr.interfaces.data_loader.DataLoaderInterface

Key Patterns:

  • @discover_data_loader decorator exposes parameters to UI and API (see Discovery Plugin)

  • Parameter schema defines type, requirement, defaults, and descriptions

  • Inherits from vipr.handlers.data_loader.DataLoaderHandler (VIPR base class)

  • Method signature matches interface: _load_data(**kwargs) -> DataSet

  • Uses VIPR path resolution for package paths

  • Returns immutable vipr.core.dataset.DataSet transfer object

  • Metadata includes loader provenance and data characteristics

HDF5 DataLoader

Handler: vipr-reflectometry:vipr_reflectometry.shared.data_loader.hdf5_spectrareader_data_loader.HDF5SpectraReaderDataLoader
Label: hdf5_spectrareader
Batch Loading: Loads multiple spectra (batch_size > 1)

Key Patterns:

ModelLoader Handlers

Reflectorch ModelLoader

Handler: vipr-reflectometry:vipr_reflectometry.reflectorch.model_loader.reflectorch_model_loader.ReflectorchModelLoader
Label: reflectorch
External Library: reflectorch (EasyInferenceModel)

Key Patterns:

  • Inherits from vipr.handlers.model_loader.ModelLoaderHandler

  • Method signature: _load_model(**kwargs) -> Any

  • Environment variable integration for paths (REFLECTORCH_ROOT_DIR)

  • Returns library-specific model object (no wrapping required)

  • Integrates with Hugging Face Hub for model downloads

Flow Model Loader

Handler: vipr-reflectometry:vipr_reflectometry.flow_models.model_loader.flow_model_loader.FlowModelLoader
Label: flow_model_loader
External Library: PyTorch + custom flow architectures

Key Patterns:

  • Inherits from vipr.handlers.model_loader.ModelLoaderHandler

  • Access inference workflow attributes: self.app.inference.device

  • Configuration loading from external libraries

  • Checkpoint loading and state dict management

  • Model preparation (device placement, eval mode)

Predictor Handlers

Reflectorch Predictor

Handler: vipr-reflectometry:vipr_reflectometry.reflectorch.predictor.reflectorch_predictor.ReflectorchPredictor
Label: reflectorch_predictor
Input: DataSet + Model
Output: Dictionary with predictions

Key Patterns:

  • Inherits from vipr.handlers.predictor.PredictorHandler

  • Access workflow state: self.app.inference.preprocessed_data, self.app.inference.model

  • Method signature: _predict(**kwargs) -> dict

  • Configurable post-processing via parameters

  • Returns structured dictionary (not DataSet)

Flow Predictor

Handler: vipr-reflectometry:vipr_reflectometry.flow_models.predictor.flow_predictor.FlowPredictor
Label: flow_predictor
Output: Posterior samples

Key Patterns:

Handler Registration

Handlers are registered in submodule load(app) functions:

# shared/__init__.py
def load(app):
    """Load shared handlers used by multiple submodules."""
    # Register shared data loaders
    app.handler.register(HDF5SpectraReaderDataLoader)
    app.handler.register(CSVSpectraReaderDataLoader)
    
    # Register shared controller
    app.handler.register(ReflectometryController)

# reflectorch/__init__.py
def load(app):
    """Load reflectorch-specific handlers."""
    # Register only reflectorch handlers
    app.handler.register(ReflectorchModelLoader)
    app.handler.register(ReflectorchPredictor)

# flow_models/__init__.py
def load(app):
    """Load flow-specific handlers."""
    # Register only flow handlers
    app.handler.register(FlowModelLoader)
    app.handler.register(FlowPredictor)

Pattern:

  • Shared handlers registered in shared/__init__.py (single source of truth)

  • Each submodule registers only its own handlers

  • Main plugin loads shared first, then submodules

Configuration Usage

Handlers are selected in YAML configuration:

vipr:
  inference:
    load_data:
      handler: csv_spectrareader  # Handler label
      parameters:
        data_path: '@vipr_reflectometry/reflectorch/examples/data/D17_SiO.dat'
        column_mapping:
          q: 0
          I: 1
          dI: 2
    
    load_model:
      handler: reflectorch  # Handler label
      parameters:
        config_name: e_mc_point_neutron_conv_standard_L1_InputQDq_n256_size1024
    
    prediction:
      handler: reflectorch_predictor  # Handler label
      parameters:
        calc_pred_curve: true
        calc_pred_sld_profile: true

Key Takeaways

Handler Implementation Checklist

  1. ✅ Inherit from appropriate base class (DataLoaderHandler, ModelLoaderHandler, PredictorHandler)

  2. ✅ Use @discover_* decorator with parameter schema

  3. ✅ Implement required method (_load_data, _load_model, _predict)

  4. ✅ Return appropriate type (DataSet, model object, dict)

  5. ✅ Register handler in submodule load(app) function

VIPR Framework Patterns Used

  • Discovery System: Parameter exposure via decorators

  • Handler Registry: Dynamic handler lookup by label

  • Transfer Object: Immutable DataSet for data flow

  • Workflow Integration: Access workflow state via self.app.inference.*

  • Configuration-Driven: YAML configuration selects handlers and parameters