data_models.features.api
data_models.features.api
Classes
| Name | Description |
|---|---|
| CategoricalInput | Base class for all categorical input features. |
| CategoricalOutput | An output whose measured value is one of a fixed set of categories. |
| ContinuousInput | Base class for all continuous input features. |
| ContinuousOutput | A numerical quantity measured for each candidate. |
| DiscreteInput | Feature with discretized ordinal values allowed in the optimization. |
| Descriptors | A rectangular block of per-level descriptor data. |
| TaskInput | Abstract base class for task-encoding inputs. |
CategoricalInput
data_models.features.api.CategoricalInput()Base class for all categorical input features.
A categorical input has one descriptor level per category, so each column of the optional descriptors block holds one value per category, in the same order as categories.
How those descriptors are turned into model columns is not fixed here: it is chosen per surrogate via categorical_encodings (e.g. OneHotEncoding or a DescriptorEncoding selecting columns and/or running descriptor generators on the structure).
Examples
>>> CategoricalInput(key="solvent", categories=["water", "ethanol", "thf"])With per-category descriptors — one value per category in each column, and one SMILES per category:
>>> CategoricalInput(
... key="solvent",
... categories=["water", "ethanol", "thf"],
... descriptors=Descriptors(
... columns={"logP": [-1.4, -0.3, 0.5], "MW": [18.0, 46.0, 72.0]},
... structure=["O", "CCO", "C1CCOC1"],
... ),
... )Methods
| Name | Description |
|---|---|
| fixed_value | Returns the categories to which the feature is fixed, None if the feature is not fixed |
| from_encoding | Back-transform encoded columns to categories with the given encoding. |
| generate_allowed | Generates the list of allowed categories if not provided. |
| get_allowed_categories | Returns the allowed categories. |
| get_forbidden_categories | Returns the non-allowed categories |
| get_possible_categories | Return the superset of categories that have been used in the experimental dataset and |
| is_fixed | Returns True if there is only one allowed category. |
| is_fulfilled | Method to check if the values are all allowed categories. |
| sample | Draw random samples from the feature. |
| to_encoding | Encode a series of categories with the given encoding. |
| to_pydantic_field | Return (Literal[...], Field(description=...)) with allowed categories. |
| valid_transform_types | Valid encoding classes for this feature. |
| validate_candidental | Method to validate the suggested candidates |
| validate_experimental | Method to validate the experimental dataFrame |
fixed_value
data_models.features.api.CategoricalInput.fixed_value(transform_type=None)Returns the categories to which the feature is fixed, None if the feature is not fixed
Returns
| Name | Type | Description |
|---|---|---|
| Union[List[str], List[float], None] | List[str]: List of categories or None |
from_encoding
data_models.features.api.CategoricalInput.from_encoding(encoding, values)Back-transform encoded columns to categories with the given encoding.
generate_allowed
data_models.features.api.CategoricalInput.generate_allowed(allowed, info)Generates the list of allowed categories if not provided.
get_allowed_categories
data_models.features.api.CategoricalInput.get_allowed_categories()Returns the allowed categories.
Returns
| Name | Type | Description |
|---|---|---|
| list[str] | list of str: The allowed categories |
get_forbidden_categories
data_models.features.api.CategoricalInput.get_forbidden_categories()Returns the non-allowed categories
Returns
| Name | Type | Description |
|---|---|---|
| List[str]: List of the non-allowed categories |
get_possible_categories
data_models.features.api.CategoricalInput.get_possible_categories(values)Return the superset of categories that have been used in the experimental dataset and that can be used in the optimization
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | Series with the values for this feature | required |
Returns
| Name | Type | Description |
|---|---|---|
| list | list | list of possible categories |
is_fixed
data_models.features.api.CategoricalInput.is_fixed()Returns True if there is only one allowed category.
Returns
| Name | Type | Description |
|---|---|---|
| bool | [bool]: True if there is only one allowed category |
is_fulfilled
data_models.features.api.CategoricalInput.is_fulfilled(values)Method to check if the values are all allowed categories.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | A series with values for the input feature. | required |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | A series with boolean values indicating if the input feature is fulfilled. |
sample
data_models.features.api.CategoricalInput.sample(n, seed=None)Draw random samples from the feature.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| n | int | number of samples. | required |
| seed | int | random seed. Defaults to None. | None |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: drawn samples. |
to_encoding
data_models.features.api.CategoricalInput.to_encoding(encoding, values)Encode a series of categories with the given encoding.
Generic pandas entry point: the encoding object owns the actual transform.
to_pydantic_field
data_models.features.api.CategoricalInput.to_pydantic_field()Return (Literal[...], Field(description=...)) with allowed categories.
When the number of allowed categories exceeds LLM_ENUM_SCHEMA_THRESHOLD the type falls back to str (the allowed values stay in the description). See the module-level comment on the constant for the reason.
Subclasses customize the output by overriding _description_prefix and/or _extra_description_parts.
Examples
>>> feat = CategoricalInput(key="solvent", categories=["water", "ethanol", "toluene"])
>>> field_type, _ = feat.to_pydantic_field()
>>> # field_type = Literal['water', 'ethanol', 'toluene']valid_transform_types
data_models.features.api.CategoricalInput.valid_transform_types()Valid encoding classes for this feature.
One-hot and ordinal are always valid; DescriptorEncoding is valid when the feature carries a descriptor block, since the encoding can read either its numeric columns or its structure.
validate_candidental
data_models.features.api.CategoricalInput.validate_candidental(values)Method to validate the suggested candidates
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | A dataFrame with candidates | required |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | when not all values for a feature are one of the allowed categories |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: The passed dataFrame with candidates |
validate_experimental
data_models.features.api.CategoricalInput.validate_experimental(
values,
strict=False,
)Method to validate the experimental dataFrame
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | A dataFrame with experiments | required |
| strict | bool | Boolean to distinguish if the occurrence of fixed features in the dataset should be considered or not. Defaults to False. | False |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | when an entry is not in the list of allowed categories | |
| ValueError | when there is no variation in a feature provided by the experimental data |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: A dataFrame with experiments |
CategoricalOutput
data_models.features.api.CategoricalOutput()An output whose measured value is one of a fixed set of categories.
The surrogate predicts a probability for each category, and the objective turns those probabilities into a reward by declaring which categories are desirable. Typical use is a pass/fail or graded quality read-out.
Examples
>>> CategoricalOutput(
... key="quality",
... categories=["pass", "fail"],
... objective=ConstrainedCategoricalObjective(
... categories=["pass", "fail"], desirability=[True, False]
... ),
... )Methods
| Name | Description |
|---|---|
| validate_objective_categories | Validates that objective categories match the output categories |
validate_objective_categories
data_models.features.api.CategoricalOutput.validate_objective_categories()Validates that objective categories match the output categories
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | when categories do not match objective categories |
Returns
| Name | Type | Description |
|---|---|---|
| self |
ContinuousInput
data_models.features.api.ContinuousInput()Base class for all continuous input features.
A continuous input is a single descriptor component: it has exactly one descriptor level (the feature itself), so each column of the optional descriptors block holds exactly one value. This is what lets a continuous feature act as one component of a mixture, blended by a WeightedSumFeature — on its own the block has no effect on the feature’s own encoding.
Examples
>>> ContinuousInput(key="temperature", bounds=(20, 80))As one component of a mixture, carrying the properties of the substance whose amount it holds — one value per column, one SMILES:
>>> ContinuousInput(
... key="ethanol",
... bounds=(0, 1),
... descriptors=Descriptors(
... columns={"logP": [-0.3], "MW": [46.0]},
... structure=["CCO"],
... ),
... )Attributes
| Name | Description |
|---|---|
| is_semicontinuous | True iff the feasible region is the disconnected union |
Methods
| Name | Description |
|---|---|
| is_fulfilled | Method to check if the values are within the bounds of the feature. |
| round | Round values to the stepsize of the feature. If no stepsize is provided return the |
| sample | Draw random samples from the feature. |
| to_pydantic_field | Return ``(float, Field(ge=…, le=…, description=…))```. |
| validate_candidental | Method to validate the suggested candidates |
is_fulfilled
data_models.features.api.ContinuousInput.is_fulfilled(values, noise=1e-05)Method to check if the values are within the bounds of the feature.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | A series with values for the input feature. | required |
| noise | float | A small value to allow for numerical errors. Defaults to 10e-6. | 1e-05 |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | A series with boolean values indicating if the input feature is fulfilled. |
round
data_models.features.api.ContinuousInput.round(values)Round values to the stepsize of the feature. If no stepsize is provided return the provided values.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | The values that should be rounded. | required |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: The rounded values |
sample
data_models.features.api.ContinuousInput.sample(n, seed=None)Draw random samples from the feature.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| n | int | number of samples. | required |
| seed | int | random seed. Defaults to None. | None |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: drawn samples. |
to_pydantic_field
data_models.features.api.ContinuousInput.to_pydantic_field()Return ``(float, Field(ge=…, le=…, description=…))```.
Subclasses customize the output by overriding _description_prefix and/or _extra_description_parts.
Examples
>>> feat = ContinuousInput(key="temp", bounds=(20.0, 200.0), context="Temperature in C")
>>> field_type, field_info = feat.to_pydantic_field()
>>> # field_type = float
>>> # field_info has ge=20.0, le=200.0
>>> # description = "Continuous, bounds [20.0, 200.0] — Temperature in C"validate_candidental
data_models.features.api.ContinuousInput.validate_candidental(values)Method to validate the suggested candidates
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | A dataFrame with candidates | required |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | when non numerical values are passed | |
| ValueError | when values are larger than the upper bound of the feature | |
| ValueError | when values are lower than the lower bound of the feature |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: The passed dataFrame with candidates |
ContinuousOutput
data_models.features.api.ContinuousOutput()A numerical quantity measured for each candidate.
Examples
>>> ContinuousOutput(key="yield", objective=MaximizeObjective())Methods
| Name | Description |
|---|---|
| to_description | Return a human-readable description combining objective and context. |
to_description
data_models.features.api.ContinuousOutput.to_description()Return a human-readable description combining objective and context.
Examples
>>> feat = ContinuousOutput(key="yield", objective=MaximizeObjective(w=1.0), context="Target >90%")
>>> feat.to_description()
'yield: Maximize — Target >90%'DiscreteInput
data_models.features.api.DiscreteInput()Feature with discretized ordinal values allowed in the optimization.
Like ContinuousInput, a discrete input is a single descriptor component: the allowed values are not descriptor levels, so each descriptors column and the structure column hold exactly one value (a restricted amount of a substance still describes one substance).
Examples
>>> DiscreteInput(key="n_layers", values=[1.0, 2.0, 4.0, 8.0])As one component of a mixture, where the restricted amounts still describe a single substance — one value per column, one SMILES:
>>> DiscreteInput(
... key="ethanol",
... values=[0.0, 0.25, 0.5],
... descriptors=Descriptors(
... columns={"logP": [-0.3], "MW": [46.0]},
... structure=["CCO"],
... ),
... )Attributes
| Name | Description |
|---|---|
| lower_bound | Lower bound of the set of allowed values |
| upper_bound | Upper bound of the set of allowed values |
Methods
| Name | Description |
|---|---|
| from_continuous | Rounds continuous values to the closest discrete ones. |
| is_fulfilled | Method to check if the values are close to the discrete values. |
| sample | Draw random samples from the feature. |
| to_pydantic_field | Return (Literal[...], Field(description=...)) with allowed values. |
| validate_candidental | Method to validate the provided candidates. |
| validate_values_unique | Validates that provided values are unique. |
from_continuous
data_models.features.api.DiscreteInput.from_continuous(values)Rounds continuous values to the closest discrete ones.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.DataFrame | Dataframe with continuous entries. | required |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: Series with discrete values. |
is_fulfilled
data_models.features.api.DiscreteInput.is_fulfilled(values)Method to check if the values are close to the discrete values.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | A series with values for the input feature. | required |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | A series with boolean values indicating if the input feature is fulfilled. |
sample
data_models.features.api.DiscreteInput.sample(n, seed=None)Draw random samples from the feature.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| n | int | number of samples. | required |
| seed | int | random seed. Defaults to None. | None |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: drawn samples. |
to_pydantic_field
data_models.features.api.DiscreteInput.to_pydantic_field()Return (Literal[...], Field(description=...)) with allowed values.
Subclasses customize the output by overriding _description_prefix and/or _extra_description_parts.
Examples
>>> feat = DiscreteInput(key="n_steps", values=[1.0, 2.0, 5.0])
>>> field_type, _ = feat.to_pydantic_field()
>>> # field_type = Literal[1.0, 2.0, 5.0]validate_candidental
data_models.features.api.DiscreteInput.validate_candidental(values)Method to validate the provided candidates.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | pd.Series | suggested candidates for the feature | required |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | Raises error when one of the provided values is not contained in the list of allowed values. |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Series | pd.Series: suggested candidates for the feature |
validate_values_unique
data_models.features.api.DiscreteInput.validate_values_unique(values)Validates that provided values are unique.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | List[float] | List of values | required |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | when values are non-unique. | |
| ValueError | when values contains only one entry. | |
| ValueError | when values is empty. |
Returns
| Name | Type | Description |
|---|---|---|
| List[values]: Sorted list of values |
Descriptors
data_models.features.api.Descriptors()A rectangular block of per-level descriptor data.
A “level” is a row of the block, providing the descriptor data for one distinct thing the feature can refer to — each molecule, say, gets its own level. How many levels a feature has is the feature’s business, not this class’s; see the examples.
Examples
On a CategoricalInput, one level per category — the block supplies the row of whichever category is chosen:
>>> Descriptors(
... columns={"logP": [-1.4, -0.3, 0.5], "MW": [18.0, 46.0, 72.0]},
... structure=["O", "CCO", "C1CCOC1"],
... )On a ContinuousInput or DiscreteInput, a single level — the feature is one component of a mixture, and its amount weights that one row:
>>> Descriptors(columns={"logP": [-0.3]}, structure=["CCO"])Attributes
| Name | Description |
|---|---|
| names | Names of the numeric descriptor columns. |
Methods
| Name | Description |
|---|---|
| concat | Stack blocks row-wise into a single block. |
| table | Per-level table (rows = index, columns = columns or all of them). |
| validate_fit | Check that this block describes exactly levels. |
| validate_rectangular | Every column and the structure must describe the same levels. |
concat
data_models.features.api.Descriptors.concat(blocks)Stack blocks row-wise into a single block.
Used to turn the one-row blocks of the components of a mixture into one block the weighted sum can read, so that both descriptor scopes end up as “a block plus an index”. The blocks must describe the same thing: same column names and either all or none carrying a structure.
Column order follows the first block, which keeps static columns ahead of generated ones — :func:filter_correlated keeps the first of each correlated group, so the order is load-bearing.
table
data_models.features.api.Descriptors.table(index, columns=None)Per-level table (rows = index, columns = columns or all of them).
validate_fit
data_models.features.api.Descriptors.validate_fit(levels)Check that this block describes exactly levels.
The block itself only guarantees internal consistency; how many levels there should be is the feature’s business, so the feature calls this from its own model validator.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| levels | List | The levels the feature carrying this block declares. | required |
Raises
| Name | Type | Description |
|---|---|---|
| ValueError | If the block describes a different number of levels. |
validate_rectangular
data_models.features.api.Descriptors.validate_rectangular()Every column and the structure must describe the same levels.
TaskInput
data_models.features.api.TaskInput()Abstract base class for task-encoding inputs.
This class is not directly instantiable and is not part of any AnyFeature/AnyInput union. Use :class:CategoricalTaskInput or :class:ContinuousTaskInput instead. It exists solely so that strategies can use isinstance(feat, TaskInput) to detect either flavour.
Task inputs carry no descriptor data: both flavours narrow descriptors to None, so it cannot be set.