data_models.features.api
data_models.features.api
Classes
| Name | Description |
|---|---|
| CategoricalInput | Base class for all categorical input features. |
| CategoricalOutput | |
| ContinuousInput | Base class for all continuous input features. |
| ContinuousOutput | The base class for a continuous output feature |
| 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::
solvent = 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"], # one SMILES per category
),
)
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).
Attributes
| Name | Type | Description |
|---|---|---|
| categories | List[str] | Names of the categories. |
| allowed | List[bool] | List of bools indicating if a category is allowed within the optimization. |
| descriptors | Descriptors | Per-category descriptor data — numeric columns and/or a SMILES structure column. Defaults to None. |
| key | str, inherited from Feature |
The unique name of the feature. |
| context | str, optional, inherited from Feature |
Free-text context for the feature. Defaults to None. |
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.
Example::
>>> 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()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::
ethanol = ContinuousInput(
key="ethanol",
bounds=(0, 1),
descriptors=Descriptors(
columns={"logP": [-0.3], "MW": [46.0]}, # one value per column
structure=["CCO"], # one SMILES
),
)
Attributes
| Name | Type | Description |
|---|---|---|
| bounds | Tuple[float, float] | A tuple that stores the lower and upper bound of the feature. |
| stepsize | PositiveFloat | Float indicating the allowed stepsize between lower and upper. Defaults to None. |
| local_relative_bounds | Tuple[float, float] | A tuple that stores the lower and upper bounds relative to a reference value. Defaults to None. |
| allow_zero | bool | A boolean indicating if the input feature can take inactive values. Useful for features that take values between bounds, but can also take a value of 0. One may choose to use a conditional kernel for this, if taking a value of 0 represents a distinct behaviour from non-zero values. |
| descriptors | Descriptors | Descriptor data for the single component — numeric columns holding one value each, and/or a one-element SMILES structure. Consumed by N-arity engineered features, not by this feature’s own encoding. Defaults to None. |
| unit | str, optional, inherited from NumericalInput |
The unit of the feature. Defaults to None. |
| key | str, inherited from Feature |
The unique name of the feature. |
| context | str, optional, inherited from Feature |
Free-text context for the feature. Defaults to None. |
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.
Example::
>>> 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()The base class for a continuous output feature
Attributes
| Name | Type | Description |
|---|---|---|
| objective | objective | objective of the feature indicating in which direction it should be optimized. Defaults to 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.
Example::
>>> 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).
Attributes
| Name | Type | Description |
|---|---|---|
| key(str) | key of the feature. | |
| values(List[float]) | the discretized allowed values during the optimization. | |
| descriptors | Descriptors | Descriptor data for the single component — numeric columns holding one value each, and/or a one-element SMILES structure. Defaults to None. |
| unit | str, optional, inherited from NumericalInput |
The unit of the feature. Defaults to None. |
| context | str, optional, inherited from Feature |
Free-text context for the feature. Defaults to None. |
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.
Example::
>>> 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. What the levels are depends on the feature the block is attached to, and is the feature’s business, not this class’s:
CategoricalInput — one level per category, so the block picks the row of the chosen category (select-row)::
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"],
),
)
ContinuousInput / DiscreteInput — a single level, the feature itself. It is one component of a mixture whose amount weights its row, so each column holds one value. For a discrete input the allowed values are not levels: a restricted amount of a substance still describes one substance::
ContinuousInput(
key="ethanol",
bounds=(0, 1),
descriptors=Descriptors(columns={"logP": [-0.3]}, structure=["CCO"]),
)
Attributes
| Name | Type | Description |
|---|---|---|
| columns | Dict[str, List[float]] | Numeric property columns, each with one value per level. |
| structure | Optional[List[str]] | Optional structure identifiers (SMILES), one per level. |
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.