Skip to content

Commit 76644d8

Browse files
committed
refactor(web): webapi states.py definitions and _status_to_stage function
Add 'warning' to post validate states
1 parent f9df01e commit 76644d8

File tree

3 files changed

+87
-94
lines changed

3 files changed

+87
-94
lines changed

tidy3d/web/api/container.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@
3737
from tidy3d.web.api.states import (
3838
COMPLETED_PERCENT,
3939
COMPLETED_STATES,
40+
DRAFT_STATES,
4041
END_STATES,
4142
ERROR_STATES,
4243
PRE_ERROR_STATES,
43-
PRE_VALIDATE_STATES,
44+
QUEUED_STATES,
4445
RUNNING_STATES,
4546
STATE_PROGRESS_PERCENTAGE,
4647
)
@@ -1067,7 +1068,7 @@ def pbar_description(
10671068
status_part = f"→ [red]{status:<{status_width}}"
10681069
elif status in COMPLETED_STATES:
10691070
status_part = f"→ [green]{status:<{status_width}}"
1070-
elif status in (PRE_ERROR_STATES | PRE_VALIDATE_STATES):
1071+
elif status in (PRE_ERROR_STATES | DRAFT_STATES | QUEUED_STATES):
10711072
status_part = f"→ [yellow]{status:<{status_width}}"
10721073
elif status in RUNNING_STATES:
10731074
status_part = f"→ [blue]{status:<{status_width}}"

tidy3d/web/api/states.py

Lines changed: 74 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
from __future__ import annotations
22

3+
# progression order for a typical run
4+
PROGRESSION_ORDER = (
5+
"draft",
6+
"queued",
7+
"preprocess",
8+
"running",
9+
"postprocess",
10+
"success",
11+
)
12+
13+
MAX_STEPS = len(PROGRESSION_ORDER) - 1
14+
COMPLETED_PERCENT = 100
15+
316
PRE_ERROR_STATES = {
417
"aborting",
518
}
@@ -18,14 +31,17 @@
1831

1932
PRE_VALIDATE_STATES = {
2033
"draft",
21-
"queued",
22-
"queued_solver",
23-
"preprocess",
2434
"validating",
2535
"validate",
2636
}
2737

28-
POST_RUN_STATES = {
38+
QUEUED_STATES = {"queued", "queued_solver"}
39+
40+
PREPROCESS_STATES = {"preprocess"}
41+
42+
RUNNING_STATES = {"running", "preprocess_success"}
43+
44+
POSTPROCESS_STATES = {
2945
"postprocess",
3046
"run_success",
3147
}
@@ -42,70 +58,66 @@
4258

4359
END_STATES = ERROR_STATES | COMPLETED_STATES
4460

45-
POST_VALIDATE_STATES = {"validate_success", "validate_warn"}
61+
POST_VALIDATE_STATES = {"validate_success", "validate_warn", "warning"}
4662

47-
RUNNING_STATES = (
48-
PRE_VALIDATE_STATES | POST_VALIDATE_STATES | {"running"} | POST_RUN_STATES | COMPLETED_STATES
49-
)
63+
DRAFT_STATES = PRE_VALIDATE_STATES | POST_VALIDATE_STATES
5064

51-
ALL_POST_VALIDATE_STATES = POST_VALIDATE_STATES | {"running"} | POST_RUN_STATES | END_STATES
65+
ALL_POST_VALIDATE_STATES = POST_VALIDATE_STATES | RUNNING_STATES | POSTPROCESS_STATES | END_STATES
5266

53-
VALID_PROGRESS_STATES = RUNNING_STATES | PRE_ERROR_STATES
67+
VALID_PROGRESS_STATES = (
68+
DRAFT_STATES
69+
| QUEUED_STATES
70+
| POST_VALIDATE_STATES
71+
| RUNNING_STATES
72+
| POSTPROCESS_STATES
73+
| COMPLETED_STATES
74+
| PRE_ERROR_STATES
75+
)
5476

5577
ALL_STATES = VALID_PROGRESS_STATES | ERROR_STATES
5678

57-
58-
PROGRESSION_ORDER = (
59-
"draft",
60-
"queued",
61-
"queued_solver",
62-
"preprocess",
63-
"validating",
64-
"validate",
65-
"validate_success",
66-
"validate_warn",
67-
"running",
68-
"postprocess",
69-
"run_success",
70-
"visualize",
71-
"success",
72-
"completed",
79+
STATE_PROGRESS_PERCENTAGE = dict.fromkeys(ALL_STATES, 0)
80+
STATE_PROGRESS_PERCENTAGE.update(dict.fromkeys(COMPLETED_STATES, COMPLETED_PERCENT))
81+
STATE_PROGRESS_PERCENTAGE.update(
82+
{state: round((1 / MAX_STEPS) * COMPLETED_PERCENT) for state in QUEUED_STATES}
83+
)
84+
STATE_PROGRESS_PERCENTAGE.update(
85+
{state: round((2 / MAX_STEPS) * COMPLETED_PERCENT) for state in PREPROCESS_STATES}
86+
)
87+
STATE_PROGRESS_PERCENTAGE.update(
88+
{state: round((3 / MAX_STEPS) * COMPLETED_PERCENT) for state in RUNNING_STATES}
89+
)
90+
STATE_PROGRESS_PERCENTAGE.update(
91+
{state: round((4 / MAX_STEPS) * COMPLETED_PERCENT) for state in POSTPROCESS_STATES}
7392
)
74-
75-
MAX_STEPS = len(PROGRESSION_ORDER) - 1
76-
COMPLETED_PERCENT = 100
7793

7894

79-
STATE_PROGRESS_PERCENTAGE = {
80-
# --- Progression States ---
81-
"draft": round((0 / MAX_STEPS) * COMPLETED_PERCENT), # 0%
82-
"queued": round((1 / MAX_STEPS) * COMPLETED_PERCENT), # 8%
83-
"queued_solver": round((2 / MAX_STEPS) * COMPLETED_PERCENT), # 15%
84-
"preprocess": round((3 / MAX_STEPS) * COMPLETED_PERCENT), # 23%
85-
"validating": round((4 / MAX_STEPS) * COMPLETED_PERCENT), # 31%
86-
"validate": round((5 / MAX_STEPS) * COMPLETED_PERCENT), # 38%
87-
"validate_success": round((6 / MAX_STEPS) * COMPLETED_PERCENT), # 46%
88-
"validate_warn": round((7 / MAX_STEPS) * COMPLETED_PERCENT), # 54%
89-
"running": round((8 / MAX_STEPS) * COMPLETED_PERCENT), # 62%
90-
"run_success": round((9 / MAX_STEPS) * COMPLETED_PERCENT), # 69%
91-
"postprocess": round((10 / MAX_STEPS) * COMPLETED_PERCENT), # 77%
92-
"visualize": round((11 / MAX_STEPS) * COMPLETED_PERCENT), # 85%
93-
"success": COMPLETED_PERCENT, # 100%
94-
"completed": COMPLETED_PERCENT, # 100%
95-
"postprocess_success": COMPLETED_PERCENT, # 100%
96-
"diverge": COMPLETED_PERCENT,
97-
"diverged": COMPLETED_PERCENT,
98-
# --- Error States ---
99-
# All error states map to 0%
100-
"validate_fail": 0,
101-
"error": 0,
102-
"errored": 0,
103-
"blocked": 0,
104-
"run_failed": 0,
105-
"aborted": 0,
106-
"deleted": 0,
107-
"validate_error": 0,
108-
"preprocess_error": 0,
109-
"run_error": 0,
110-
"postprocess_error": 0,
111-
}
95+
def status_to_stage(status: str) -> tuple[str, int]:
96+
"""Map task status to monotonic stage for progress bars.
97+
98+
Parameters
99+
----------
100+
status : str
101+
The task status string.
102+
103+
Returns
104+
-------
105+
tuple[str, int]
106+
A tuple of (stage_name, stage_index) where stage_index corresponds
107+
to the position in PROGRESSION_ORDER.
108+
"""
109+
s = (status or "").lower()
110+
if s in DRAFT_STATES:
111+
return ("draft", 0)
112+
if s in QUEUED_STATES:
113+
return ("queued", 1)
114+
if s in PREPROCESS_STATES:
115+
return ("preprocess", 2)
116+
if s in RUNNING_STATES:
117+
return ("running", 3)
118+
if s in POSTPROCESS_STATES:
119+
return ("postprocess", 4)
120+
if s in COMPLETED_STATES:
121+
return ("success", 5)
122+
# Unknown states map to earliest stage to avoid showing 100% prematurely
123+
return (s or "unknown", 0)

tidy3d/web/api/webapi.py

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
ALL_POST_VALIDATE_STATES,
2424
END_STATES,
2525
ERROR_STATES,
26+
MAX_STEPS,
2627
STATE_PROGRESS_PERCENTAGE,
28+
status_to_stage,
2729
)
2830
from tidy3d.web.cache import CacheEntry, _store_mode_solver_in_cache, resolve_local_cache
2931
from tidy3d.web.core.account import Account
@@ -1192,28 +1194,6 @@ def load(
11921194
return stub_data
11931195

11941196

1195-
def _status_to_stage(status: str) -> tuple[str, int]:
1196-
"""Map task status to monotonic stage for progress bars."""
1197-
s = (status or "").lower()
1198-
# Map a broader set of states to monotonic stages for progress bars
1199-
if s in ("draft", "created"):
1200-
return ("draft", 0)
1201-
if s in ("queue", "queued"):
1202-
return ("queued", 1)
1203-
if s in ("validating",):
1204-
return ("validating", 2)
1205-
if s in ("validate_success", "validate_warn", "preprocess", "preprocessing"):
1206-
return ("preprocess", 3)
1207-
if s in ("running", "preprocess_success"):
1208-
return ("running", 4)
1209-
if s in ("run_success", "postprocess"):
1210-
return ("postprocess", 5)
1211-
if s in ("success", "postprocess_success"):
1212-
return ("success", 6)
1213-
# Unknown states map to earliest stage to avoid showing 100% prematurely
1214-
return (s or "unknown", 0)
1215-
1216-
12171197
def _monitor_modeler_batch(
12181198
task_id: str,
12191199
verbose: bool = True,
@@ -1230,7 +1210,7 @@ def _monitor_modeler_batch(
12301210
# Non-verbose path: poll without progress bars then return
12311211
if not verbose:
12321212
# Run phase
1233-
while _status_to_stage(status)[0] not in END_STATES:
1213+
while status_to_stage(status)[0] not in END_STATES:
12341214
time.sleep(REFRESH_TIME)
12351215
detail = _get_batch_detail_handle_error_status(task)
12361216
status = detail.status.lower()
@@ -1252,8 +1232,8 @@ def _monitor_modeler_batch(
12521232
# Phase: Run (aggregate + per-task)
12531233
p_run = progress.add_task("Run Total", total=1.0)
12541234
task_bars: dict[str, int] = {}
1255-
stage = _status_to_stage(status)[0]
1256-
prev_stage = _status_to_stage(status)[0]
1235+
stage = status_to_stage(status)[0]
1236+
prev_stage = status_to_stage(status)[0]
12571237
console.log(f"Batch status = {status}")
12581238

12591239
# Note: get_status errors if an erroring status occurred
@@ -1270,7 +1250,7 @@ def _monitor_modeler_batch(
12701250
for name, t in name_to_task.items():
12711251
if name not in task_bars:
12721252
tstatus = (t.status or "draft").lower()
1273-
_, idx = _status_to_stage(tstatus)
1253+
_, idx = status_to_stage(tstatus)
12741254
pbar = progress.add_task(
12751255
f" {name}",
12761256
total=1.0,
@@ -1285,8 +1265,8 @@ def _monitor_modeler_batch(
12851265
for t in detail.tasks or []:
12861266
n_members += 1
12871267
tstatus = (t.status or "draft").lower()
1288-
_, idx = _status_to_stage(tstatus)
1289-
acc += max(0.0, min(1.0, idx / 6.0))
1268+
_, idx = status_to_stage(tstatus)
1269+
acc += max(0.0, min(1.0, idx / MAX_STEPS))
12901270
run_frac = (acc / float(n_members)) if n_members else 0.0
12911271
else:
12921272
run_frac = (r / total) if total else 0.0
@@ -1300,7 +1280,7 @@ def _monitor_modeler_batch(
13001280
if not t:
13011281
continue
13021282
tstatus = (t.status or "draft").lower()
1303-
_, idx = _status_to_stage(tstatus)
1283+
_, idx = status_to_stage(tstatus)
13041284
desc = f" {tname} [{tstatus or 'draft'}]"
13051285
progress.update(
13061286
pbar,
@@ -1313,7 +1293,7 @@ def _monitor_modeler_batch(
13131293
time.sleep(REFRESH_TIME)
13141294
detail = _get_batch_detail_handle_error_status(task)
13151295
status = detail.status.lower()
1316-
stage = _status_to_stage(status)[0]
1296+
stage = status_to_stage(status)[0]
13171297

13181298
if console is not None:
13191299
console.log("Modeler has finished running successfully.")

0 commit comments

Comments
 (0)