Skip to content

Getting started

Install itis-sumo, then build, cross-validate, and interrogate one surrogate end to end. Every step below is real, runnable code — the same pipeline examples/headless_smoke.py runs as a CI smoke test.

1. Install

uv sync                          # Python 3.12-3.14; resolves itis-dakota==6.24.13
uv run itis-sumo validate        # engine probe (expect: Version 6.24.13)

Engine gate

If validate fails, the Dakota engine wheel didn't resolve — an install problem, not an itis-sumo problem. Nothing below works until it passes.

2. Some training data

itis-sumo trains on whatever x -> y observations you already have — from a simulator, an experiment, a spreadsheet. Here we fake 30 noisy observations of a made-up stress = f(length, width) relationship so the tutorial doesn't depend on external data:

import numpy as np
import pandas as pd

rng = np.random.default_rng(42)
length = rng.uniform(0.0, 1.0, size=30)
width = rng.uniform(0.0, 1.0, size=30)
stress = (
    3.0 * length
    + 2.0 * width**2
    + 0.5 * np.sin(10.0 * length)
    + rng.normal(0, 0.05, 30)
)
train_raw = pd.DataFrame({"length": length, "width": width, "stress": stress})

3. Preprocess: raw names → Dakota-safe names

itis-sumo's Dakota layer expects standardized variable names (x1, x2, … / y1, y2, …), not your original column names — DataPreprocessor handles that mapping (plus optional normalization) both ways:

from itis_sumo.preprocess.data_preprocessor import DataPreprocessor

preprocessor = DataPreprocessor()
preprocessor.setup_variables(["length", "width"], ["stress"])
preprocessor.fit(train_raw)
train_processed = preprocessor.transform(train_raw)

training_file = run_dir / "df_processed_jobs.dat"
train_processed.to_csv(training_file, sep=" ", index=False)

run_dir is any writable directory — itis_sumo.utils.helpers.create_run_dir makes one for you with a timestamp-scoped name.

4. Fit a surrogate and evaluate it

from itis_sumo.evaluate.funs_evaluate import evaluate_sumo

preds = evaluate_sumo(run_dir, training_file, eval_samples_file, ["x1", "x2"], "y1")
y_hat = preds["y1_hat"]  # posterior mean prediction at each eval point

evaluate_sumo fits a Gaussian Process on training_file and predicts at every point in eval_samples_file (built the same way as the training file — see the full script for the grid-construction step omitted here for brevity). What a GP is and why itis-sumo uses one: How Gaussian Processes work.

5. How good is it? Cross-validate

from itis_sumo.evaluate.funs_evaluate import evaluate_sumo_crossvalidation

cv_metrics = evaluate_sumo_crossvalidation(
    run_dir, training_file, ["x1", "x2"], "y1", N_CROSS_VALIDATION=5
)
print(cv_metrics["y1"]["root_mean_squared"])

5-fold CV, held-out RMSE. This is the number that tells you whether to trust the surrogate on points you didn't train on — see How-to: cross-validate a surrogate for the full recipe including R² and convergence checks.

6. Which inputs actually matter? Sobol' sensitivity

from itis_sumo.evaluate.funs_evaluate import evaluate_sobol_indices

sampling = {
    "length": {"minimum": 0.0, "maximum": 1.0},
    "width": {"minimum": 0.0, "maximum": 1.0},
}
sobol = evaluate_sobol_indices(
    run_dir,
    training_file,
    ["length", "width"],
    "y1",
    sampling,
    preprocessor,
    seed=42,
)["sobol"]
for var, indices in sobol.items():
    print(var, indices["main"], indices["total"])

First- and total-order Sobol' indices per variable — see How-to: run sensitivity analysis.

Run it for real

uv run python examples/headless_smoke.py   # the whole thing above, in one script
uv run pytest                              # itis-sumo's own test suite

Where next

  • Building something real? Start with the How-to guides — task recipes for cross-validation, sensitivity/UQ, MOGA optimization, and preprocessing.
  • Want to see it against real data end to end? Worked examples.
  • Curious why surrogate modeling and GPs work the way they do? Why surrogate modeling.
  • Need exact function signatures? Reference.