Skip to content

Commit e133a2b

Browse files
committed
Added result_identifiers and included fails in returned results
1 parent 20afd29 commit e133a2b

File tree

4 files changed

+58
-15
lines changed

4 files changed

+58
-15
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,4 @@ cython_debug/
151151
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
152152
#.idea/
153153
tests/test_data/stored_results.xlsx
154+
/tests/test_data/design

src/xl_engine/excel_engine.py

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def excel_runner(
1717
dynamic_inputs: dict[str, dict[str, float]],
1818
save_conditions: dict[str, callable],
1919
static_identifier_keys: Optional[list[str]] = None,
20+
result_labels: Optional[dict[str, str]] = None,
2021
save_dir: Optional[str] = None,
2122
sheet_idx: int = 0,
2223
) -> None:
@@ -42,12 +43,18 @@ def excel_runner(
4243
'save_conditions': a dictionary keyed by cell references whose values are unary callables
4344
which return a bool when passed the value retrieved from the workbook at the cell
4445
reference during each iteration. If all callables in the 'save_conditions' dict
45-
return True, then that iteration of the workbook will be saved to disk.
46+
return True, then that iteration of the workbook will be saved to disk. Use the
47+
create_condition_check() function in this module to quickly create such callables.
4648
'static_identifier_keys': The keys in 'static_inputs', which are not cell references,
4749
which will be used to create unique filenames whenever the save conditions are all
4850
True. e.g. if there is a key in 'static_inputs' called 'Label', then passing a list
4951
of ['Label'] as the static_identifier_keys will ensure that the data under the 'Label'
5052
key will be used as part of the unique filename.
53+
'result_labels': A mapping of result cell references to what those cell references mean
54+
for a human. e.g. if the result cell B6 referred to a "shear utilization ratio" then
55+
the result_label dict might look like this: {"B6": "shear utilization ratio"}
56+
The result label will be used in the returned results. If None, then the cell references
57+
will be used instead.
5158
'save_dir': The directory to store saved workbooks
5259
'sheet_idx': The sheet to modify within the workbook.
5360
"""
@@ -73,6 +80,7 @@ def excel_runner(
7380
panel = Panel(progress_group)
7481

7582
main_task = main_progress.add_task("Primary Iterations", total=iterations)
83+
dynamic_results = {}
7684
with Live(panel) as live:
7785
for iteration in range(iterations):
7886
demand_cells_to_change = {
@@ -85,8 +93,13 @@ def excel_runner(
8593
for cell_id in demand_cell_ids
8694
if not valid_excel_reference(cell_id)
8795
}
96+
if identifier_values:
97+
identifiers = "-".join([static_inputs[id_key][iteration] for id_key in static_identifier_keys])
98+
else:
99+
identifiers = f"{iteration}"
88100
variations_task = variations_progress.add_task("Sheet variations", total=len(dynamic_inputs.items()))
89101
variations_progress.reset(variations_task)
102+
failed_results = {}
90103
for design_tag, design_cells_to_change in dynamic_inputs.items():
91104
cells_to_change = demand_cells_to_change | design_cells_to_change
92105
calculated_results = execute_workbook(
@@ -95,7 +108,13 @@ def excel_runner(
95108
cells_to_retrieve=list(save_conditions.keys()),
96109
sheet_idx=sheet_idx
97110
)
98-
111+
if isinstance(result_labels, dict):
112+
labeled_results = {result_labels[k]: v for k, v in calculated_results.items()}
113+
else:
114+
labeled_results = calculated_results
115+
116+
failed_results.update({design_tag: labeled_results})
117+
99118
save_condition_acc = []
100119
for result_cell_id, save_condition in save_conditions.items():
101120
calculated_result = calculated_results[result_cell_id]
@@ -106,28 +125,27 @@ def excel_runner(
106125
filepath = pathlib.Path(xlsx_filepath)
107126
name = filepath.stem
108127
suffix = filepath.suffix
109-
if identifier_values:
110-
identifiers = "-".join([static_identifier_keys[id_key] for id_key in static_identifier_keys])
111-
else:
112-
identifiers = f"{iteration}"
113128

114129
new_filename = f"{name}-{identifiers}-{design_tag}{suffix}"
115130
save_dir_path = pathlib.Path(save_dir)
116131
if not save_dir_path.exists():
117132
save_dir_path.mkdir(parents=True)
118-
calculated_results = execute_workbook(
133+
_ = execute_workbook(
119134
xlsx_filepath,
120135
cells_to_change=cells_to_change,
121136
cells_to_retrieve=list(save_conditions.keys()),
122137
new_filepath=f"{str(save_dir)}/{new_filename}",
123138
sheet_idx=sheet_idx,
124139
)
140+
dynamic_results.update({identifiers: {"successful_key": design_tag} | labeled_results})
125141
variations_progress.remove_task(variations_task)
126142
break
127143
else:
128144
variations_progress.remove_task(variations_task)
145+
dynamic_results.update({identifiers: {"successful_key": None} | failed_results})
129146
progress_group.renderables.append(Text(f"Variation: {iteration} did not meet the criteria"))
130147
main_progress.update(main_task, advance=1)
148+
return dynamic_results
131149

132150

133151
def execute_workbook(
@@ -158,6 +176,23 @@ def execute_workbook(
158176
locations. Can be a str or pathlib.Path. Directories on
159177
the path must already exist because this function will not create them if
160178
they do not.
179+
180+
### Example:
181+
182+
dcr2 = xl.create_condition_check(2, "ge")
183+
results = xl.excel_runner(
184+
"example_wb.xlsx",
185+
static_inputs={"B1": [10, 20], "Labels": ["C01", "C02"]},
186+
dynamic_inputs={
187+
"OptA": {"B2": 22},
188+
"OptB": {"B2": 33},
189+
"OptC": {"B2": 55},
190+
},
191+
save_conditions={"B6": dcr2},
192+
static_identifier_keys=["Labels"],
193+
result_labels={"B6": "meaningful_value"},
194+
save_dir=TEST_DATA_DIR / "design"
195+
)
161196
"""
162197
xlsx_filepath = pathlib.Path(xlsx_filepath)
163198
if not xlsx_filepath.exists():
@@ -209,6 +244,12 @@ def create_condition_check(check_against_value: float, op: str) -> callable:
209244
'check_against_value' the value that will be encoded in the function
210245
to check against.
211246
'op': str, one of {"ge", "le", "gt", "lt", "eq", "ne"}
247+
- "ge" Greater-than-or-equal-to
248+
- "le" Less-than-or-equal-to
249+
- "gt" Greater-than
250+
- "lt" Less-than
251+
- "eq" Equal-to
252+
- "ne" Not-equal-to
212253
"""
213254
operators = {
214255
"ge": operator.ge,

tests/test_excel_engine.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,18 @@ def test_execute_workbook():
4343

4444
def test_excel_runner():
4545
dcr2 = xl.create_condition_check(2, "ge")
46-
xl.excel_runner(
46+
results = xl.excel_runner(
4747
TEST_DATA_DIR / "example_wb.xlsx",
48-
demand_input_cell_arrays={"B1": [10, 20], "Labels": ["R", "S"]},
49-
design_inputs={
48+
static_inputs={"B1": [10, 20], "Labels": ["C01", "C02"]},
49+
dynamic_inputs={
5050
"OptA": {"B2": 22},
5151
"OptB": {"B2": 33},
5252
"OptC": {"B2": 55},
5353
},
54-
result_cells=["B4", "B5", "B6"],
5554
save_conditions={"B6": dcr2},
56-
identifier_keys=["Labels"],
55+
static_identifier_keys=["Labels"],
56+
result_labels={"B6": "meaningful_value"},
5757
save_dir=TEST_DATA_DIR / "design"
58-
)
58+
)
59+
assert results['C01']['successful_key'] is None # No match found
60+
assert results['C02']['successful_key'] == "OptA" # Option A worked passed the criteria

uv.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)