Frequently Asked Questions#
How do I install optional dependencies (FEniCS, scikit-image)?#
PyOED’s core functionality requires only NumPy, SciPy, Matplotlib, Pandas, and Seaborn. Some submodules require optional dependencies:
FEniCS (
fenics-dolfin) – PDE-based simulation models.scikit-image – coherent diffraction imaging (CDI) models.
multiprocess – parallel ensemble evaluations.
Tests for optional-dependency modules are automatically skipped when the corresponding package is not installed. Install them via conda or pip as needed:
conda install -c conda-forge fenics-dolfin
pip install scikit-image multiprocess
Why do I get a PyOEDConfigsValidationError?#
This exception is raised when a configuration value fails validation. Common causes:
Passing a configuration key that doesn’t exist in the
*Configsclass.Providing a value of the wrong type (e.g., a string where a float is expected).
Registering components with inconsistent dimensions (e.g., an observation operator whose domain doesn’t match the model state size).
Check the error message for the specific validation rule that failed, and
inspect your configurations via obj.configurations.
What does PROJECT_ONTO_ACTIVE_DESIGN_SPACE do?#
This global setting (in pyoed.configs.SETTINGS) controls how observation
vectors are interpreted when an experimental design is active:
``False`` (default): observation vectors are stored and used in the full observation space, regardless of which design elements are active.
``True``: observation vectors are projected onto the active subspace defined by the current design, reducing their dimension.
This affects the observation operator, observation error model, and the
observations property of inverse problems.
How do I create a custom optimality criterion?#
Subclass the criterion base class from
pyoed.oed.core.utility_functions and implement the evaluate
method. The minimum required interface is:
from pyoed.oed.core.utility_functions import InversionCriterion
class MyCriterion(InversionCriterion):
def evaluate(self, design):
"""
:param design: 1-D numpy array of length n_y (the design vector).
:returns: scalar float — lower is better (OED minimises this).
"""
# Example: negative sum of active sensor weights (trivial criterion)
return -float(design.sum())
Then register it with an OED problem:
oed_problem.register_optimality_criterion(MyCriterion())
Enabling gradient-based optimization:
If you want the criterion to work with ScipyOptimizer
using gradient information, also implement grad_design:
class MyCriterion(InversionCriterion):
def evaluate(self, design):
return -float(design.sum())
def grad_design(self, design):
"""Gradient of evaluate() w.r.t. design."""
import numpy as np
return -np.ones_like(design)
Criteria that expose grad_design satisfy the
SupportsRelaxedOptimization protocol and
are automatically detected as gradient-capable by the OED solver.
Tip: If you do not implement grad_design, PyOED falls back to
finite-difference gradient estimation automatically.
How do I run only a subset of tests?#
PyOED uses pytest markers to tag tests by subpackage:
pytest -m "configs" # only configuration tests
pytest -m "oed" # only OED tests
pytest -m "not fenics" # skip FEniCS tests
Available markers: examples, simulation_models, error_models,
observation_operators, utility, optimization, assimilation,
stats, distributions, oed, utility_functions, fenics,
configs, cdi.