Skip to content

Required Feature Attributes

Overview

The RequiredFeatureAttributes class is a subclass of CalculationRequirement that is used to check if a list of attributes is set for a feature of an object. This is useful when a calculation requires a specific set of attributes to be present for a feature, and it is necessary to check if they exist before proceeding with the calculation.

Usage

This requirement can be instantiated with a list of attributes that need to be present for each feature of an object. Below there is an example of how to use this requirement:

requirement = RequiredFeatureAttributes(object_name="LAN-LAN-01", feature_name="cms_amplitude_01_filter", attributes=["feature_options_json"])

After calling check and get_data methods, the data attribute of the requirement will be a dictionary with the feature as the key and a dictionary with the attributes as the value. Below there is an example of how this data is stored:

{
    "feature_options_json": {"kind": "amplitude", "sensor": 1, "acquisition": "filter"}
}

Database Requirements

This requirement expects that the feature_attributes table is set with the necessary attributes for each feature. This can easily be done with the database function set_attribute. Below is a query example to set the attributes for the feature cms_amplitude_01_filter of the model G97-2.07 of the object LAN-LAN-01:

SELECT * FROM performance.fn_set_feature_attribute('cms_amplitude_01_filter', 'G97-2.07', 'feature_options_json', '{"attribute_value": {"kind": "amplitude", "sensor": 1, "acquisition": "filter"}}');

To check if the attributes are set correctly, go to the v_feature_attributes view in the database.

Class Definition

RequiredFeatureAttributes(object_name, feature_name, attributes, optional=False)

Subclass of CalculationRequirement that defines the feature attributes that are required for the calculation.

This will check the performance database for the existence of the required feature attributes for the wanted object and feature.

Parameters:

  • object_name

    (str) –

    Name of the object for which the feature attributes are required.

  • feature_name

    (str) –

    Name of the feature for which the attributes are required.

  • attributes

    (list[str]) –

    The attributes that are required for the feature.

  • optional

    (bool, default: False ) –

    Set to True if this is an optional requirement. by default False

Source code in echo_energycalc/calculation_requirement_feature_attributes.py
def __init__(
    self,
    object_name: str,
    feature_name: str,
    attributes: list[str],
    optional: bool = False,
) -> None:
    """
    Constructor of the RequiredFeatureAttributes class.

    This will check the performance database for the existence of the required feature attributes for the wanted object and feature.

    Parameters
    ----------
    object_name : str
        Name of the object for which the feature attributes are required.
    feature_name : str
        Name of the feature for which the attributes are required.
    attributes : list[str]
        The attributes that are required for the feature.
    optional : bool, optional
        Set to True if this is an optional requirement. by default False
    """
    super().__init__(optional)

    # check if object_name is a str
    if not isinstance(object_name, str):
        raise TypeError(f"object_name must be a str, not {type(object_name)}")

    self._object = object_name

    # check if feature_name is a str
    if not isinstance(feature_name, str):
        raise TypeError(f"feature_name must be a str, not {type(feature_name)}")

    self._feature = feature_name

    # check if attributes is a list of str
    if not isinstance(attributes, list):
        raise TypeError(f"attributes must be a list, not {type(attributes)}")
    if not all(isinstance(item, str) for item in attributes):
        raise TypeError(f"all attributes items must be str, not {[type(item) for item in attributes]}")

    self._attributes = attributes

attributes property

Attributes that are required for the feature.

Returns:

  • list[str]

    The attributes that are required for the feature.

checked property

Attribute that defines if the requirement has been checked. It's value will start as False and will be set to True after the check method is called.

Returns:

  • bool

    True if the requirement has been checked.

data property

Data required for the calculation.

Returns:

  • dict[str, Any]

    Dict with the required feature attributes for the desired feature. The keys are the attribute names and the values are the attribute values.

feature property

Name of the feature for which the attributes are required.

Returns:

  • str

    Name of the feature for which the attributes are required.

object property

Name of the object for which the feature attributes are required.

Returns:

  • str

    Name of the object for which the feature attributes are required.

optional property

Attribute that defines if the requirement is optional.

If optional is True, the requirement is only validated to check if it could exist, not if it is actually present. This is useful for requirements that are not necessary for all calculations, but are useful for some of them.

Returns:

  • bool

    True if the requirement is optional.

check()

Method used to check if the required feature attributes are present in the performance database.

This will raise an error if any of the required attributes are missing.

This method will also act like the "get_data" method because it will need to get the attributes to check if they are ok anyway, so we will store the data in the object property "data" to avoid querying the database again.

Returns:

  • bool

    True if all required feature attributes are present in the database for the feature.

Source code in echo_energycalc/calculation_requirement_feature_attributes.py
def check(self) -> bool:
    """
    Method used to check if the required feature attributes are present in the performance database.

    This will raise an error if any of the required attributes are missing.

    This method will also act like the "get_data" method because it will need to get the attributes to check if they are ok anyway, so we will store the data in the object property "data" to avoid querying the database again.

    Returns
    -------
    bool
        True if all required feature attributes are present in the database for the feature.
    """
    # checking if object exists
    objects_def = self._perfdb.objects.instances.get(object_names=[self.object])
    if not objects_def:
        raise ValueError(f"Object {self.object} does not exist in performance_db")
    obj_model = objects_def[self.object]["object_model_name"]

    # checking if feature exists
    features_def = self._perfdb.features.definitions.get(
        object_models=[obj_model],
        feature_names=[self.feature],
        output_type="dict",
        get_attributes=True,
        attribute_names=self.attributes,
    )

    features_def = features_def[obj_model]
    if len(features_def) == 0:
        raise ValueError(f"Feature {self.feature} does not exist for object {self.object} in performance_db")

    # checking if all required attributes are present
    exist_attributes = features_def[self.feature]
    missing_attributes = set(self.attributes) - set(exist_attributes.keys())
    if len(missing_attributes) > 0 and not self.optional:
        raise ValueError(f"Attributes {missing_attributes} do not exist for feature '{self.feature}' of object '{self.object}'")

    # filtering existing attributes to only include the required attributes
    exist_attributes = {attr: exist_attributes[attr] for attr in self.attributes if attr in exist_attributes}

    # saving attributes to self._data
    self._data = copy.deepcopy(exist_attributes)

    self._checked = True

    return True

get_data(**kwargs)

Method used to get the required feature attributes from performance database.

This will not do anything other than call the check() method because the check() method already gets the data.

Returns:

  • dict[str, Any]

    Dict in the format {attribute_name: attribute_value, ...}.

Source code in echo_energycalc/calculation_requirement_feature_attributes.py
def get_data(self, **kwargs) -> dict[str, Any]:  # noqa: ARG002
    """
    Method used to get the required feature attributes from performance database.

    This will not do anything other than call the check() method because the check() method already gets the data.

    Returns
    -------
    dict[str, Any]
        Dict in the format {attribute_name: attribute_value, ...}.
    """
    # in case check() was not called before get_data(), calling it now
    if not self._checked:
        self.check()

    # nothing else needs to be done here because check() already gets the data

    return self.data