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

1from django.db import models 

2 

3from core.auxiliary.models.IndexedItem import IndexedItem 

4from core.managers import AccessControlManager 

5from core.auxiliary.models.ControlValue import ControlValue 

6 

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) 

16 

17 objects = AccessControlManager() 

18 

19 class Meta: 

20 ordering = ['created_at'] 

21 

22 def enable(self, state = True) -> None: 

23 self.enabled = state 

24 self.save() 

25 

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) 

31 

32 def has_value(self) -> bool: 

33 return self.value not in [None, ""] 

34 

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) 

46 

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()] 

55 

56 def is_control_set_point(self) -> bool: 

57 return hasattr(self, "controlSetPoint") 

58 

59 def is_control_manipulated(self) -> bool: 

60 return hasattr(self, "controlManipulated") 

61 

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 

75 

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() 

81 

82 

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) 

86 

87PropertyValueIntermediate = PropertyValue.indexedItems.through 

88 

89 

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) 

98 

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] 

108 

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