Configuration
The GRAFT is configured through YAML files in app/configs/ and
shared constants in app/configs/constants.py. No code changes are needed
when tuning model parameters, switching data sources, or adjusting thresholds
— edit the relevant file and restart the application.
Config File Overview
Section titled “Config File Overview”| File | Purpose |
|---|---|
database_config.yaml | WebSocket endpoint and SQLite database path |
LinearRegression_config_NiceGUI.yaml | Linear regression model and evaluation settings |
LSTM_config_NiceGUI.yaml | LSTM architecture, features, training, and evaluation settings |
XGBoost_config_NiceGUI.yaml | XGBoost hyperparameters, features, and evaluation settings |
constants.py | Runtime constants, directory paths, labels — set once, used everywhere |
database_config.yaml
Section titled “database_config.yaml”Controls how the application connects to the live data source and where the local results database lives.
# WebSocket configurationwebsocket: # WebSocket endpoint for streaming experiment data uri: wss://maple.containers.wur.nl/ws
# Base SQL query used by the WebSocket backend base_query: SELECT * FROM public.pioreactor
# Local database configurationdatabase: # SQLite database file used for metrics and predictions path: metrics.dbwebsocket.uri — The WebSocket server to connect to. Update this if your
Pioreactor instance moves to a different host.
websocket.base_query — The SQL query sent to the WebSocket backend.
The application appends WHERE clauses for experiment filtering and time
pagination automatically — do not add these manually.
database.path — Path to the local SQLite file where prediction results
and evaluation metrics are stored. Relative paths are resolved from the
project root.
LinearRegression_config_NiceGUI.yaml
Section titled “LinearRegression_config_NiceGUI.yaml”data: id_column: entity metric_column: metric plot_history_minutes: 20 target_column: optical_density time_column: time
database: path: "metrics.db"
forecast: horizon_forecast: 15 horizon_minutes: 1
training: window_train: 300 window_test: 50
lags: number: 15
model: linear_regression_path: trained_models/linear_regression_model.pkl copy_X: True fit_intercept: True n_jobs: 1
preprocessing: fill_method: bfill_ffill resample_freq: 1min value_column: value feature_columns: - optical_density
db_config: database_config.yaml
evaluation: max_horizon: 6 rolling_window_size: 30 horizon_unit: "min" min_points_for_correlation: 20 min_variance_for_correlation: 1e-4Key Parameters
Section titled “Key Parameters”| Parameter | Default | Description |
|---|---|---|
forecast.horizon_forecast | 15 | Number of future time steps to predict |
forecast.horizon_minutes | 1 | Duration of each time step in minutes |
training.window_train | 300 | Number of most recent rows used for training |
training.window_test | 50 | Number of rows held out for testing |
lags.number | 15 | Number of lag features added to the feature matrix |
preprocessing.resample_freq | 1min | Resampling frequency applied before training |
evaluation.rolling_window_size | 30 | Rolling window of predictions used for metric computation |
evaluation.min_points_for_correlation | 20 | Minimum matched points before computing R² / Spearman |
LSTM_config_NiceGUI.yaml
Section titled “LSTM_config_NiceGUI.yaml”data: id_column: entity metric_column: metric plot_history_minutes: 20 target_column: optical_density time_column: time
database: path: "metrics.db"
forecast: horizon_forecast: 15 horizon_minutes: 1
lags: number: 60
gompertz: enabled: true adaptive_window: 300 refit_every: 10 min_points: 20 use_residual_learning: true
model: sequence_length: 60 lstm_path: trained_models/lstm_model.keras lstm_units: 100 dropout: 0.3 epochs: 5 batch_size: 32 optimizer: "adam" loss: "mae" max_rows: 10000 patience: 20 scale_target: false
preprocessing: fill_method: bfill_ffill use_log: true resample_freq: 1min value_column: value
feature_columns: - optical_density - temperature - agitation_rate - optical_density_roll3 - optical_density_roll5 - optical_density_roll10 - optical_density_std3 - optical_density_std5 - optical_density_diff1 - optical_density_diff_roll5 - experiment_elapsed_min - tod_sin - tod_cos
training: window_train: 500 window_test: 50
evaluation: max_horizon: 6 rolling_window_size: 30 horizon_unit: "min" min_points_for_correlation: 20 min_variance_for_correlation: 1e-5Key Parameters
Section titled “Key Parameters”| Parameter | Default | Description |
|---|---|---|
model.sequence_length | 60 | Look-back window (number of time steps fed into the LSTM) |
model.lstm_units | 100 | Number of LSTM units per layer |
model.dropout | 0.3 | Dropout rate applied during training |
model.epochs | 5 | Maximum training epochs (early stopping via patience) |
model.patience | 20 | Early stopping patience in epochs |
model.scale_target | false | Whether to normalise the target variable before training |
preprocessing.use_log | true | Apply log transform to optical density before training |
gompertz.enabled | true | Whether to fit a Gompertz residual correction on top of LSTM |
gompertz.adaptive_window | 300 | Recent points used for Gompertz fitting |
gompertz.refit_every | 10 | Refit the Gompertz model every N predictions |
lags.number | 60 | Number of lag features added to the input |
Feature Columns
Section titled “Feature Columns”The LSTM uses 13 engineered features derived from raw sensor data:
| Feature | Description |
|---|---|
optical_density | Raw OD reading |
temperature | Temperature (°C) |
agitation_rate | Agitation speed (RPM) |
optical_density_roll3/5/10 | Rolling mean over 3, 5, 10 steps |
optical_density_std3/5 | Rolling standard deviation over 3, 5 steps |
optical_density_diff1 | First-order difference |
optical_density_diff_roll5 | Rolling mean of first-order differences |
experiment_elapsed_min | Minutes since experiment start |
tod_sin / tod_cos | Sine and cosine encoding of time-of-day |
XGBoost_config_NiceGUI.yaml
Section titled “XGBoost_config_NiceGUI.yaml”db_config: database_config.yaml
forecast: horizon_forecast: 15 horizon_minutes: 1
lags: number: 60
model: learning_rate: 0.01 max_depth: 6 n_estimators: 100 objective: reg:squarederror tree_method: hist subsample: 0.8 colsample_bytree: 0.8 reg_lambda: 1.0
preprocessing: fill_method: bfill_ffill use_log: true resample_freq: 1min value_column: value
feature_columns: - optical_density - temperature - agitation_rate - optical_density_roll3 - optical_density_roll5 - optical_density_roll10 - optical_density_std3 - optical_density_std5 - optical_density_diff1 - optical_density_diff_roll5 - experiment_elapsed_min - tod_sin - tod_cos
training: window_train: 500 window_test: 50
data: id_column: entity metric_column: metric plot_history_minutes: 20 target_column: optical_density time_column: time
database: path: "metrics.db"
gompertz: enabled: true adaptive_window: 300 refit_every: 10 min_points: 20 use_residual_learning: true
evaluation: max_horizon: 6 rolling_window_size: 30 horizon_unit: "min" min_points_for_correlation: 20 min_variance_for_correlation: 1e-4Key Parameters
Section titled “Key Parameters”| Parameter | Default | Description |
|---|---|---|
model.n_estimators | 100 | Number of boosting rounds |
model.max_depth | 6 | Maximum tree depth — increase for more complex patterns |
model.learning_rate | 0.01 | Step size shrinkage to prevent overfitting |
model.subsample | 0.8 | Fraction of rows sampled per tree |
model.colsample_bytree | 0.8 | Fraction of features sampled per tree |
model.reg_lambda | 1.0 | L2 regularisation term |
gompertz.enabled | true | Fit a Gompertz residual correction on top of XGBoost |
preprocessing.use_log | true | Apply log transform to optical density |
XGBoost uses the same 13 engineered feature columns as the LSTM — see the LSTM feature table above.
constants.py
Section titled “constants.py”Defines application-wide runtime constants, directory paths, and display labels. These are set once and used across all modules.
Runtime Constants
Section titled “Runtime Constants”| Constant | Default | Description |
|---|---|---|
RUN_INTERVAL | 180 | Seconds between automatic prediction runs |
MAX_PLOT_POINTS | 1000 | Maximum data points rendered per chart |
AVERAGE_FREQ | "1min" | Default resampling frequency for plots |
Directory Paths
Section titled “Directory Paths”| Constant | Path | Description |
|---|---|---|
PACKAGE_DIR | Project root | Base directory for config file resolution |
USER_DATA_DIR | ~/.graft/ | User-writable runtime data directory |
MODEL_DIR | ~/.graft/trained_models/ | Saved model artefacts |
Subdirectories results/, logs/, data/, and trained_models/ are
created automatically inside USER_DATA_DIR on first run.
Labels
Section titled “Labels”METRIC_LABELS maps internal column names to human-readable axis labels:
| Key | Display Label |
|---|---|
optical_density | Optical Density (OD) |
growth_rate | Growth Rate (1/h) |
agitation_rate | Agitation Rate (RPM) |
temperature | Temperature (°C) |
MODEL_METRIC_LABELS maps evaluation metric keys to display labels:
| Key | Display Label |
|---|---|
mse | Mean Squared Error (MSE) |
rmse | Root Mean Squared Error (RMSE) |
r2 | R² Score |
spearman | Spearman Correlation |
mae | Mean Absolute Error (MAE) |
mape | MAPE (%) |
direction_accuracy | Direction Accuracy (%) |
smape | sMAPE (%) |
max_error | Maximum Error |
Changing Parameters
Section titled “Changing Parameters”You do not need to edit YAML files directly. All model parameters — training window sizes, forecast horizons, hyperparameters, and preprocessing settings — can be adjusted from within the dashboard itself on the Model Control page.
- Open the dashboard at
http://localhost:8080 - Navigate to the Model Control page
- Adjust the parameters using the input controls

- Click Run to apply the new settings and retrain or re-run the model

The YAML files in app/configs/ serve as the default values loaded on
startup. Any changes made in the app take effect immediately for that session.