Coverage for backend/django/core/auxiliary/methods/export_scenario_data.py: 81%
48 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
1"""Legacy scenario export helpers.
3These functions still export the older Solution/PropertyValue data model and are
4not part of the object-storage CSV import pipeline used by DataColumn/DataRow/DataCell.
5That separation is intentional for now and round-tripping through CSV import/export
6should not be assumed here.
7"""
9from core.auxiliary.models.Scenario import Scenario
10from core.auxiliary.models.Flowsheet import Flowsheet
11from core.auxiliary.models.PropertyValue import PropertyValue
12from core.auxiliary.models.Solution import Solution
15def values_per_index(scenario: Scenario):
16 if not scenario.enable_dynamics: 16 ↛ 19line 16 didn't jump to line 19 because the condition on line 16 was always true
17 return 1
18 else :
19 return scenario.num_time_steps
21# Tested in test_mss.py
22def export_scenario_data(flowsheet: Flowsheet, scenario: Scenario, properties: list[int] | None = None):
23 # Create a column for each property value
24 if properties:
25 solutions = Solution.objects.filter(scenario=scenario, property__property_id__in=properties).order_by("solve_index")
26 else:
27 solutions = Solution.objects.filter(scenario=scenario).order_by("solve_index")
29 property_values = (
30 PropertyValue.objects.filter(
31 flowsheet_state=flowsheet.current_state,
32 solutions__in=solutions,
33 )
34 .distinct()
35 .values(
36 'id',
37 'property__displayName',
38 'property__set__simulationObject__componentName',
39 'indexedItems__displayName'
40 )
41 )
43 # Temp container
44 grouped_data = {}
45 # Group indexed items by property value id
46 for row in property_values:
47 pv_id = row['id']
49 if pv_id not in grouped_data:
50 grouped_data[pv_id] = {
51 'uo_name': row['property__set__simulationObject__componentName'],
52 'prop_name': row['property__displayName'],
53 'indices': []
54 }
56 if row['indexedItems__displayName']:
57 grouped_data[pv_id]['indices'].append(row['indexedItems__displayName'])
59 # Create a list of blanks to fill in missing data
60 blanks = [None for _ in range(values_per_index(scenario))]
62 columns = {}
63 data = {}
65 for pv_id, info in grouped_data.items():
66 base_name = f"{info['uo_name']} - {info['prop_name']}"
67 index_names = " - ".join(info['indices']) # e.g Phases -> Liquid water, Phases -> Vapor water
68 column_name = f"{base_name} ({index_names})" if index_names else base_name
70 columns[pv_id] = column_name
71 data[column_name] = []
73 # Populate the columns
74 current_solve_index = 0
76 for solution in solutions:
77 if solution.solve_index > current_solve_index:
78 # Fill in blanks for missing solve indices
79 for _ in range(solution.solve_index - current_solve_index - 1): 79 ↛ 80line 79 didn't jump to line 80 because the loop on line 79 never started
80 for column_name in data.keys():
81 data[column_name].extend(blanks)
82 current_solve_index = solution.solve_index
84 column_name = columns[solution.property_id]
85 # Because the values are an array, we flatten them into the data column
86 data[column_name].extend(solution.values)
88 return data
90def collate(data: dict[str,list]):
91 """
92 Collate the data into rows for CSV export
93 """
94 # Collate the data into rows
95 # Each row is a dict with keys as column names
96 rows = []
97 max_length = max((len(v) for v in data.values()),default=0)
98 for i in range(max_length): 98 ↛ 99line 98 didn't jump to line 99 because the loop on line 98 never started
99 row = {}
100 for key, values in data.items():
101 row[key] = values[i] if i < len(values) else None
102 rows.append(row)
103 return rows