Coverage for backend/django/idaes_factory/adapters/property_info_adapter.py: 99%
62 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
1from abc import ABC
2from typing import TYPE_CHECKING
4from ahuora_builder_types import PropertySchema, PropertiesSchema, PropertyValueSchema
5from common.config_types import *
6from ..queryset_lookup import get_property
7from .convert_expression import convert_expression
8from .property_value_adapter import serialise_property_value
9from .serialisation_rules import is_group_enabled
11if TYPE_CHECKING:
12 from core.auxiliary.models.PropertyInfo import PropertyInfo
13 from ..idaes_factory_context import IdaesFactoryContext
15def serialise_property_info(ctx, property_info: "PropertyInfo",
16 is_tear: bool = False,
17 is_indexed: bool = True) -> PropertySchema:
18 """
19 A PropertyInfo object represents a single IndexedVar or ScalarVar in IDAES.
20 This method handles unpacking the indexes and putting it in the format that
21 idaes_service expects. see pump.json or any of the other idaes_service test files
22 as an example of what a property looks like.
23 """
25 property_values = property_info.values.all()
27 has_value = False
29 if ctx.scenario != None:
30 enable_rating = ctx.scenario.enable_rating
31 else:
32 enable_rating = False
34 data = []
36 for prop in property_values:
37 # get indexes
38 # ie. ["0", "benzene", "Vap"]
39 from core.auxiliary.models.PropertyValue import sort_indexes
41 unsorted_indexes = list(prop.indexedItems.all())
43 # Get the object type and property key (e.g.: split_fraction)
44 property_key = property_info.key
45 schema = property_info.set.simulationObject.schema
46 if property_key not in schema.properties:
47 # e.g machine learning block: doesn't use the normal property schema methods.
48 index_set_order = []
49 else:
50 index_set_order : list[str] = property_info.set.simulationObject.schema.properties[property_key].indexSets
52 # Sort the indexes so that they are in the order defined in the config file
53 # and continue serialization with the new indexes
54 indexes = [index.key for index in sort_indexes(index_set_order, unsorted_indexes)]
56 # get value data
57 # ie. {"id": 1, "value": 0.5, "controlled": int?, "guess": bool?, "constraint": str?} value_data = {
58 property_value = PropertyValueSchema(
59 id=prop.id,
60 discrete_indexes=indexes,
61 )
62 value = serialise_property_value(ctx, property_info, prop, is_indexed, is_tear=is_tear)
63 if value is not None:
64 has_value = True # used to determine if we should include the unit
65 if is_tear:
66 # only pass value for tear variables
67 property_value.value = value
68 if (
69 prop.is_control_set_point()
70 and prop.is_externally_controlled()
71 ):
72 # this property is externally controlled, and will be included
73 # on the other side of the tear. So we need to set the id to -1
74 # to avoid clashing ids.
75 # We need to discard this one because this side is just a guess,
76 # while the other may be used for constraints which can be
77 # deactivated during optimization.
78 property_value.id = -1
79 else:
80 property_value.value = value
81 if (prop.is_control_set_point()):
82 if not enable_rating:
83 # get the id of the thing we're manipulating
84 property_value.controlled = prop.controlSetPoint.manipulated.id
85 else:
86 property_value.value = None
88 if prop.formula not in [None, ""]:
89 property_value.constraint = convert_expression(prop.formula, ctx, prop)
90 if (prop.is_control_manipulated()
91 and not enable_rating):
92 property_value.guess = True
94 # track dependencies
95 ctx.add_property_value_dependency(prop)
97 data.append(property_value)
99 property_schema = PropertySchema(data=data)
100 if has_value:
101 property_schema.unit = property_info.unit
103 return property_schema
107class ValueAdapter(ABC):
108 def serialise(self, ctx, model):
109 pass
114class SerialisePropertiesAdapter(ValueAdapter):
115 """
116 This class replaced PropertyDictAdapter and PropertyKeyAdapter.
117 """
119 def serialise(self, ctx, model, is_tear: bool = False) -> PropertiesSchema:
120 """
121 Serialise all properties in the model.
122 """
123 property_set = model.properties
125 result: PropertiesSchema = {}
127 prop_key: str
128 prop_schema: PropertyType
129 for prop_key,prop_schema in model.schema.properties.items():
130 # if the propertySetGroup is not enabled, don't serialise this property
131 if not is_group_enabled(model, ctx, prop_key):
132 continue
133 # if schema type is not number, skip it too
134 if prop_schema.type != "numeric":
135 continue
136 # get the property from the unit model
137 prop = get_property(property_set, prop_key)
138 # serialise the property
139 result[prop_key] = serialise_property_info(
140 ctx,
141 prop,
142 is_tear=is_tear, # tears and streams are handled separately
143 is_indexed=prop_schema.hasTimeIndex
144 )
145 return result