Coverage for backend/core/auxiliary/models/PropertyValue.py: 93%
58 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1from django.db import models
3from core.auxiliary.models.IndexedItem import IndexedItem
4from core.managers import AccessControlManager
5from core.auxiliary.models.ControlValue import ControlValue
7class PropertyValue(models.Model):
8 flowsheet = models.ForeignKey("Flowsheet", on_delete=models.CASCADE, related_name="propertyValues")
9 value = models.JSONField(null=True, blank=True)
10 displayValue = models.JSONField(null=True, blank=True)
11 enabled = models.BooleanField(default=True)
12 formula = models.CharField(max_length=2048, null=True, blank=True, default=None)
13 property = models.ForeignKey("PropertyInfo", on_delete=models.CASCADE, related_name="values", null=True)
14 indexedItems = models.ManyToManyField(IndexedItem, related_name="propertyValues")
15 created_at = models.DateTimeField(auto_now_add=True)
17 objects = AccessControlManager()
19 class Meta:
20 ordering = ['created_at']
22 def enable(self, state = True) -> None:
23 self.enabled = state
24 self.save()
26 def get_index(self, index_set: str) -> list[IndexedItem]:
27 """
28 Get the indexed item of the specified type for this property.
29 """
30 return self.indexedItems.get(type=index_set)
32 def has_value(self) -> bool:
33 return self.value not in [None, ""]
35 def get_indexed_items(self) -> list[IndexedItem]:
36 """
37 Gets the list of indexed items for this property value, in order
38 Note that this is kinda expensive if you're doing it for everything,
39 as it looks up the unit op type every time.
40 But it's helpful for testing.
41 """
42 indexes = list(self.indexedItems.all())
43 property_key = self.property.key
44 index_set_order = self.property.set.simulationObject.schema.properties[property_key].indexSets
45 return sort_indexes(index_set_order, indexes)
47 def get_indexes(self) -> list[str]:
48 """
49 Gets the list of indexes for this property value, in order. e.g "outlet_1
50, Note that this is kinda expensive if you're doing it for everything,
51 as it looks up the unit op type every time.
52 But it's helpful for testing.
53 """
54 return [index.key for index in self.get_indexed_items()]
56 def is_control_set_point(self) -> bool:
57 return hasattr(self, "controlSetPoint")
59 def is_control_manipulated(self) -> bool:
60 return hasattr(self, "controlManipulated")
62 def is_externally_controlled(self) -> bool:
63 """
64 Returns true if the property is controlled or controlling an external property
65 """
66 if not self.is_control_manipulated() and not self.is_control_set_point():
67 return False
68 if self.is_control_manipulated():
69 # set point is from a different property set
70 return self.controlManipulated.setPoint.property.set != self.property.set
71 if self.is_control_set_point(): 71 ↛ 74line 71 didn't jump to line 74 because the condition on line 71 was always true
72 # manipulated property is from a different property set
73 return self.controlSetPoint.manipulated.property.set != self.property.set
74 return False
76 def is_enabled(self) -> bool:
77 """
78 Returns true if the property is to be enabled in simulation: either a statevar or a controlled property
79 """
80 return (self.enabled and not self.is_control_manipulated() ) or self.is_control_set_point()
83 def add_control(self, prop: "PropertyValue") -> ControlValue:
84 # This property is the set point controlling the manipulated property
85 return ControlValue.create(setPoint=self, manipulated=prop, flowsheet=prop.flowsheet)
87PropertyValueIntermediate = PropertyValue.indexedItems.through
90def sort_indexes(index_set_order : list[str], indexes : list[IndexedItem]) -> list[IndexedItem]:
91 """
92 Sorts the list of indexed items based on the order defined in the config file.
93 index_set_order: list[str], a list of index set types, the order in which the indexes should be sorted. e.g ["splitter_fraction","compound","phase"]
94 indexes: list[IndexedItem], a list of indexed items to be sorted. e.g a list of indexed items attached to a PropertyValue
95 """
96 item = [index.type for index in indexes]
97 reordered_indexes = [None] * len(indexes)
99 for i in range(len(item)):
100 if item[i] != index_set_order[i]:
101 # Find the correct position for the current item in object_properties
102 correct_position = index_set_order.index(item[i])
103 # Place the current index in the correct position
104 reordered_indexes[correct_position] = indexes[i]
105 else:
106 # If the item is already in the correct position, keep it as is
107 reordered_indexes[i] = indexes[i]
109 # Update the original indexes list with the reordered indexes
110 for i in range(len(indexes)):
111 indexes[i] = reordered_indexes[i]
112 return indexes