Model Computation¶
doetools fits one ordinary least-squares (MLR) model for each imported response. The same configured model matrix is used for every response. The fitted models provide coefficients, ANOVA data, diagnostic metrics, and model-based plots.
This section covers model setup, fitting, and the available summary tables.
Quick Navigation:
Set Model Terms - Define polynomial structure
Set Response Condition - Define optimization goals
Compute MLR Model - Fit regression models
Model Statistics - Access regression results and diagnostics
Note
Before computing models, ensure:
that you have imported your response data using
import_responses()that you have defined the appropriate model terms (linear, interaction, quadratic) via
set_model_terms()
Response conditions are optional. Set them with set_response_conditions()
only for Pareto analysis or plots that use response limits and objectives.
Set Model Terms¶
Define the terms to include in the regression model. "all" includes every
available term of that type; use None to omit a term type.
Note
If you want to visualize the leverage surface you need to set the model terms first.
- Design.set_model_terms(terms)[source]¶
Specify the model terms for regression analysis.
Compiles
termsfor the factors in this design and builds the model matrix used for fitting. Process-factor terms include main effects, interactions, and quadratics; mixture terms are specified through the Scheffe options onModelTerms.- Parameters:
terms (
ModelTerms) – Requested process and mixture model terms.- Raises:
ValueError – If the requested terms are invalid for the design or the compiled model has more terms than experimental runs.
- Return type:
None
Notes
The model matrix is constructed from the coded design matrix. Calling this method again replaces the previous model specification and matrix.
The ModelTerms class provides a convenient way to specify model terms:
- class doetools.ModelTerms(intercept=True, pro_main='all', pro_int2='all', pro_quadratic='all', pro_int3=None, scheffe_pol_order=None, mix_main=None, mix_int2=None, mix_int3=None)[source]¶
Request specification for model terms in process and mixture designs.
This class is used to specify which terms should be included in a model before it is compiled into a ModelSpec. It supports both process factors (with quadratic terms) and mixture factors (with Scheffe polynomials).
- Parameters:
intercept (
bool) – Whether to include an intercept. It cannot be used with mixture factors. Defaults toTrue.pro_main (
Union[Literal['all'],list[str],None]) – Process main effects. Defaults to"all".pro_int2 (
Union[Literal['all'],list[tuple[str,str]],None]) – Two-factor process interactions. Defaults to"all".pro_quadratic (
Union[Literal['all'],list[str],None]) – Process quadratic terms. Defaults to"all".pro_int3 (
Union[Literal['all'],list[tuple[str,str,str]],None]) – Three-factor process interactions. Defaults toNone.scheffe_pol_order (
int|None) – Scheffe polynomial order for mixture factors (1, 2, or 3). Defaults toNone.mix_main (
Union[Literal['all'],list[str],None]) – Mixture main effects. Defaults toNone.mix_int2 (
Union[Literal['all'],list[tuple[str,str]],None]) – Two-component mixture terms. Defaults toNone.mix_int3 (
Union[Literal['all'],list[tuple[str,str,str]],None]) – Three-component mixture terms. Defaults toNone.
Notes
Setting
scheffe_pol_orderfills in unspecified mixture terms. Order 1 includes main effects, order 2 also includes two-component terms, and order 3 also includes three-component terms.
Example:
from doetools import ModelTerms
# Screening: main effects only
terms = ModelTerms(
intercept=True,
pro_main="all",
pro_int2=None,
pro_quadratic=None,
)
design.set_model_terms(terms)
# Optimization: full quadratic model
terms = ModelTerms(
intercept=True,
pro_main="all",
pro_int2="all",
pro_quadratic="all",
)
design.set_model_terms(terms)
# Mixture design: quadratic Scheffe polynomial
terms = ModelTerms(
intercept=False,
pro_main=None,
pro_int2=None,
pro_quadratic=None,
scheffe_pol_order=2,
)
design.set_model_terms(terms)
Set Response Condition¶
Set optional optimization goals for each response: lower/upper reference limits and maximize/minimize flags. These conditions are not used to fit the MLR model. Pareto analysis uses only the maximize/minimize directions; response limits are displayed as plot guides and do not remove Pareto candidates.
- Design.set_response_conditions(lower_limits, upper_limits, maximize)[source]¶
Define optimization criteria for response variables.
Objective directions are used by Pareto analysis. Lower and upper limits are reference guides for plots and do not remove Pareto candidates. Conditions are not required to fit an MLR model. Response names must already have been defined, normally by passing
responsestoexport_experiments.- Parameters:
lower_limits (
List[float|None]) – Lower limits in response-list order. UseNonewhere no lower limit is required.upper_limits (
List[float|None]) – Upper limits in response-list order. UseNonewhere no upper limit is required.maximize (
List[bool]) – Whether to maximize (True) or minimize (False) each response.
- Raises:
ValueError – If a supplied list does not have one entry for every response, a limit is non-finite, or a lower limit exceeds its upper limit.
TypeError – If limits are not numeric or
None, or directions are not booleans.
- Return type:
None
Example:
# Maximize yield, minimize cost, target range for purity
design.set_response_conditions(
lower_limits=[70, None, 95], # 70% min yield, no min cost, 95% min purity
upper_limits=[None, 200, 100], # no max yield, $200 max cost, 100% max purity
maximize=[True, False, True] # maximize yield & purity, minimize cost
)
Compute MLR Model¶
Fit separate MLR models using the defined model terms and imported responses. The method also identifies replicate groups, which are used for pure-error and lack-of-fit calculations when applicable.
- Design.compute_mlr_model()[source]¶
Fit multiple linear regression models to the response data.
Fits one ordinary least-squares model for each imported response using the current model matrix. Replicate groups are identified automatically and used in the pure-error and lack-of-fit calculations when applicable.
- Raises:
ValueError – If responses have not been imported or model terms have not been defined.
- Return type:
None
Notes
Call
set_model_terms()andimport_responses()before fitting. The fitted models are then available to prediction and summary getters, and model-based plots.
Example:
# After importing responses and setting model terms
design.compute_mlr_model()
Compute a Pareto Front¶
After fitting the response models and assigning an objective direction (maximize or minimize) to each
selected response, evaluate the models over a deterministic candidate grid.
factor_levels selects exact continuous and categorical levels. Unspecified
process factors use all their declared levels. Use mixture_grid for mixture
resolution.
- Design.compute_pareto_front(responses=None, *, factor_levels=None, mixture_include=(), mixture_grid=None, max_candidates=100000)¶
Compute the Pareto front over every domain-valid candidate.
Response lower and upper limits are reference guides for plots; they do not restrict Pareto candidates. Factor bounds, mixture constraints, and filters set with
set_domain_filtersdefine the candidate domain.- Return type:
None
design.compute_pareto_front(
responses=["Yield", "Cost"],
factor_levels={
"Temperature": [40, 50, 60],
"Catalyst": ["A", "C"],
},
)
Response lower and upper limits are not hard constraints in this computation. They remain reference guides on the resulting 2D Pareto plot.
Model Statistics¶
These methods summarize in compact pd.DataFrame tables the results of regression analysis, including coefficient estimates, ANOVA results, model quality metrics, and diagnostic tests.
Coefficient Summary¶
Get regression coefficients with standard errors and significance tests.
- DesignSummaryMixin.get_coefficient_summary(response)[source]¶
Return a defensive copy of a response coefficient table.
- Return type:
DataFrame
Example:
coef_summary = design.get_coefficient_summary(response="Yield")
print(coef_summary)
# Output columns: Variable | Coefficient | Std_Error | Conf_Int |
# Lower_CI | Upper_CI | p_value
ANOVA Summary¶
Get ANOVA decomposition table.
- DesignSummaryMixin.get_anova_summary(response)[source]¶
Return ANOVA dataframe for the specified response
- Return type:
DataFrame
Example:
anova_summary = design.get_anova_summary(response="Yield")
print(anova_summary)
# Output columns: Source | SS | df | MS
# Pure Error and Lack of Fit rows are included only when available.
Diagnostic Metrics¶
Get model quality metrics (R², Adjusted R², RMSE, etc.).
- DesignSummaryMixin.get_metric_summary(response)[source]¶
Return a defensive one-row table of fitted model metrics.
- Return type:
DataFrame
Example:
metric_summary = design.get_metric_summary(response="Yield")
print(metric_summary)
# Output columns: R2 | R2_adj | Q2 | PRESS | RMSE | RMSE_CV
Model F-test¶
Get F-test results for overall model significance.
- DesignSummaryMixin.get_model_f_test(response)[source]¶
Return the fitted-model F test for one response.
- Return type:
DataFrame
Example:
f_test = design.get_model_f_test(response="Yield")
print(f_test)
# Output columns: F_value | F_crit_95% | F_crit_99% | p_value
Interpretation:
Null Hypothesis: All coefficients (except intercept) are zero
p-value < 0.05: Model is statistically significant (reject null hypothesis)
p-value > 0.05: Model does not explain variance better than the mean
Lack-of-Fit Test¶
Get lack-of-fit F-test results. The method returns an empty table if the fitted model has no usable pure-error and lack-of-fit degrees of freedom.
- DesignSummaryMixin.get_lof_f_test(response)[source]¶
Return LOF F-test results, or an empty table when no LOF exists.
- Return type:
DataFrame
Example:
lof_test = design.get_lof_f_test(response="Yield")
print(lof_test)
# Output columns: F_value | F_crit_95% | F_crit_99% | p_value
Interpretation:
Null Hypothesis: No lack of fit (model is adequate)
p-value > 0.05: Cannot detect lack of fit → model is adequate
p-value < 0.05: Significant lack of fit → model inadequate (add terms or transform)
Requires replicates: Pure error needed to separate model inadequacy from noise
Variance Inflation Factors¶
Get variance inflation factors to detect multicollinearity.
- DesignSummaryMixin.get_vif()[source]¶
Return a defensive copy of model-matrix VIF diagnostics.
- Return type:
DataFrame
Example:
vif_summary = design.get_vif()
print(vif_summary)
# Output columns: Term | VIF
Interpretation:
VIF = 1: No multicollinearity
VIF < 5: Low multicollinearity (good)
5 ≤ VIF < 10: Moderate multicollinearity (potential concern)
VIF ≥ 10: High multicollinearity (problematic - inflates standard errors)
Dispersion Matrix¶
Get coefficient dispersion (covariance) matrix.
- DesignSummaryMixin.get_dispersion_matrix(response, tol=1e-08)[source]¶
Return a full-precision, copy-safe parameter dispersion matrix.
- Return type:
DataFrame
Example:
dispersion = design.get_dispersion_matrix(response="Yield")
print(dispersion)
Interpretation:
Diagonal elements: Variances of coefficient estimates
Off-diagonal elements: Covariances between coefficient estimates
Replicate Summary¶
Get statistics for replicate groups.
- DesignSummaryMixin.get_replicate_summary(response)[source]¶
Return replicate statistics, or an empty table when not applicable.
- Return type:
DataFrame
Example:
replicate_summary = design.get_replicate_summary(response="Yield")
print(replicate_summary)
# Output columns: Run Index | n* | Mean | Var | Std Dev | dof
Interpretation:
n*: Number of replicates at that design point
Mean: Average response across replicates
Var / Std Dev: Measurement variability at that point
High variance: Inconsistent measurements