labnotes 0.0.64__tar.gz → 0.0.65__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {labnotes-0.0.64 → labnotes-0.0.65}/PKG-INFO +1 -1
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/list_experiments.py +3 -3
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/experiment.js +0 -5
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/labnotes.css +0 -47
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/summarize_config.py +0 -1
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/templates/experiment.html +1 -12
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/templates/index.html +1 -18
- labnotes-0.0.64/src/labnotes/cell_progress.py +0 -22
- labnotes-0.0.64/src/labnotes/experiment_progress.py +0 -27
- labnotes-0.0.64/src/labnotes/templates/macros.html +0 -10
- {labnotes-0.0.64 → labnotes-0.0.65}/.gitignore +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/CHANGELOG.md +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/MIGRATIONS.md +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/README.md +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/pyproject.toml +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/__init__.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/cli.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/context.md +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/create_app.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/create_note.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/data_html.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/experiment_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/experiments.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/format_value.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/init.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/load_config.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/models.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/modes.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/output_html.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/read_config.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/read_path.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/hold_folder.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/new_param_run_id.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/param_run_name.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/run_experiment.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/start_experiment.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/wait_for_group.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/save_note.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/server.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/testing-conventions.toml +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/tests/integration/conftest.py +0 -0
- {labnotes-0.0.64 → labnotes-0.0.65}/uv.lock +0 -0
|
@@ -4,7 +4,7 @@ from typing import cast
|
|
|
4
4
|
from dirsql import DirSQL
|
|
5
5
|
|
|
6
6
|
from labnotes.check_counts import check_counts
|
|
7
|
-
from labnotes.
|
|
7
|
+
from labnotes.count_runs import count_runs
|
|
8
8
|
from labnotes.experiment_runs import experiment_runs
|
|
9
9
|
from labnotes.summarize_config import summarize_config
|
|
10
10
|
|
|
@@ -21,8 +21,8 @@ async def list_experiments(tables: DirSQL, mode: str) -> list[dict[str, object]]
|
|
|
21
21
|
varies = cast(dict[str, list[object]], summary["varies"])
|
|
22
22
|
source = experiment_runs(name, list(varies))
|
|
23
23
|
summary = await check_counts(tables, source, summary)
|
|
24
|
-
|
|
24
|
+
[totals] = await count_runs(tables, source, str(summary["completed_run"]))
|
|
25
25
|
listed.append(
|
|
26
|
-
{"name": name, "display_name": row["display_name"], **summary, **
|
|
26
|
+
{"name": name, "display_name": row["display_name"], **summary, **totals}
|
|
27
27
|
)
|
|
28
28
|
return listed
|
|
@@ -19,11 +19,6 @@ const expand = (group, open) => {
|
|
|
19
19
|
document.addEventListener("click", (event) => {
|
|
20
20
|
const header = event.target.closest(".group-row");
|
|
21
21
|
if (header) expand(header.parentElement, !header.parentElement.classList.contains("open"));
|
|
22
|
-
const row = event.target.closest(".run-row");
|
|
23
|
-
if (!row || getSelection().toString()) return;
|
|
24
|
-
const record = row.nextElementSibling;
|
|
25
|
-
record.hidden = !record.hidden;
|
|
26
|
-
row.setAttribute("aria-expanded", String(!record.hidden));
|
|
27
22
|
});
|
|
28
23
|
|
|
29
24
|
const filters = document.querySelector("#run-filters");
|
|
@@ -54,8 +54,6 @@ code, pre, .mono { font-family: var(--mono); font-size: 0.86em; }
|
|
|
54
54
|
code { background: var(--chip); padding: 0.1em 0.35em; border-radius: 4px; }
|
|
55
55
|
|
|
56
56
|
.num { font-variant-numeric: tabular-nums; }
|
|
57
|
-
.muted { color: var(--ink-3); }
|
|
58
|
-
.of { color: var(--ink-3); }
|
|
59
57
|
|
|
60
58
|
.masthead {
|
|
61
59
|
display: flex;
|
|
@@ -120,24 +118,6 @@ h3 {
|
|
|
120
118
|
background: var(--surface);
|
|
121
119
|
}
|
|
122
120
|
|
|
123
|
-
/* Meter: one hue, track drawn from the same ramp. */
|
|
124
|
-
.meter {
|
|
125
|
-
display: block;
|
|
126
|
-
position: relative;
|
|
127
|
-
height: 4px;
|
|
128
|
-
min-width: 3rem;
|
|
129
|
-
border-radius: 2px;
|
|
130
|
-
background: var(--track);
|
|
131
|
-
overflow: hidden;
|
|
132
|
-
}
|
|
133
|
-
.meter-fill {
|
|
134
|
-
position: absolute;
|
|
135
|
-
inset: 0 auto 0 0;
|
|
136
|
-
width: calc(var(--share) * 100%);
|
|
137
|
-
border-radius: 2px;
|
|
138
|
-
background: var(--accent);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
121
|
/* Index ledger */
|
|
142
122
|
.ledger {
|
|
143
123
|
width: 100%;
|
|
@@ -167,15 +147,6 @@ h3 {
|
|
|
167
147
|
.title-link { font-family: var(--serif); font-size: 1.15rem; text-decoration: none; white-space: nowrap; }
|
|
168
148
|
.ledger .study { white-space: nowrap; }
|
|
169
149
|
|
|
170
|
-
.design { color: var(--ink-2); font-size: 0.88rem; }
|
|
171
|
-
.factor { white-space: nowrap; line-height: 1.9; }
|
|
172
|
-
.factor b { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
|
|
173
|
-
.times { color: var(--ink-3); margin-left: 0.45rem; }
|
|
174
|
-
|
|
175
|
-
.progress-col { width: 30%; }
|
|
176
|
-
.progress-line { display: grid; grid-template-columns: 1fr auto 3rem; align-items: center; gap: 0.9rem; }
|
|
177
|
-
.progress-line .num { text-align: right; }
|
|
178
|
-
.pct { color: var(--ink-2); }
|
|
179
150
|
|
|
180
151
|
.chip {
|
|
181
152
|
font-family: var(--mono);
|
|
@@ -313,11 +284,8 @@ h3 {
|
|
|
313
284
|
.runs-table .filters .pick input { width: auto; }
|
|
314
285
|
.runs-table .filters input:focus, .runs-table .filters select:focus { outline: none; border-color: var(--accent); }
|
|
315
286
|
.runs-table tbody tr:last-child td { border-bottom: 0; }
|
|
316
|
-
.run-row { cursor: pointer; }
|
|
317
287
|
.run-row td { max-width: 24rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
318
288
|
.run-row:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }
|
|
319
|
-
.run-row[aria-expanded="true"] { background: color-mix(in srgb, var(--accent) 6%, transparent); }
|
|
320
|
-
.record-row td { background: var(--paper); }
|
|
321
289
|
.group-row { cursor: pointer; background: var(--paper); }
|
|
322
290
|
.group-row td { font-weight: 600; white-space: nowrap; }
|
|
323
291
|
.group-row .good { color: var(--good); }
|
|
@@ -379,18 +347,6 @@ h3 {
|
|
|
379
347
|
.status.bad { color: var(--bad); }
|
|
380
348
|
.counts-error { color: var(--bad); }
|
|
381
349
|
|
|
382
|
-
.record {
|
|
383
|
-
display: grid;
|
|
384
|
-
grid-template-columns: max-content minmax(0, 1fr);
|
|
385
|
-
gap: 0.45rem 1.5rem;
|
|
386
|
-
margin: 0;
|
|
387
|
-
padding: 0.5rem 0 0.75rem 2.25rem;
|
|
388
|
-
}
|
|
389
|
-
.record dt { font-family: var(--mono); font-size: 0.78rem; color: var(--ink-3); }
|
|
390
|
-
.record dd { margin: 0; min-width: 0; }
|
|
391
|
-
.record code { background: none; padding: 0; word-break: break-word; }
|
|
392
|
-
.record pre { margin: 0; white-space: pre-wrap; word-break: break-word; max-height: 22rem; overflow: auto; font-size: 0.78rem; color: var(--ink-2); }
|
|
393
|
-
|
|
394
350
|
/* Index view toggle */
|
|
395
351
|
.view-toggle {
|
|
396
352
|
float: right;
|
|
@@ -431,14 +387,11 @@ h3 {
|
|
|
431
387
|
}
|
|
432
388
|
.ledger[data-view="cards"] tbody tr:hover { background: var(--surface); border-color: var(--accent); }
|
|
433
389
|
.ledger[data-view="cards"] td { display: block; padding: 0; border: 0; text-align: left; }
|
|
434
|
-
.ledger[data-view="cards"] .progress-col { width: auto; }
|
|
435
390
|
.ledger[data-view="cards"] td[data-label]::before { content: attr(data-label) " "; color: var(--ink-3); font-size: 0.82rem; }
|
|
436
391
|
|
|
437
392
|
@media (max-width: 52rem) {
|
|
438
393
|
main, .masthead { padding-left: 1.1rem; padding-right: 1.1rem; }
|
|
439
394
|
h1 { font-size: 2rem; }
|
|
440
|
-
.ledger .design { display: none; }
|
|
441
|
-
.progress-col { width: auto; }
|
|
442
395
|
}
|
|
443
396
|
|
|
444
397
|
/* Runnable python blocks in notes */
|
|
@@ -21,7 +21,6 @@ def summarize_config(config: dict[str, object] | None, mode: str) -> dict[str, o
|
|
|
21
21
|
"varies": varies,
|
|
22
22
|
"cell_count": cells,
|
|
23
23
|
"runs_per_cell": repeats,
|
|
24
|
-
"target": cells * repeats if repeats is not None and fill else None,
|
|
25
24
|
"completed_run": counts if isinstance(counts, str) else DEFAULT_COUNTS,
|
|
26
25
|
"mode": "fill" if fill else "adhoc",
|
|
27
26
|
"other": {} if command is None else {"command": command},
|
|
@@ -86,21 +86,10 @@
|
|
|
86
86
|
</tr>
|
|
87
87
|
</thead>
|
|
88
88
|
{% macro run_rows(run) %}
|
|
89
|
-
<tr class="run-row"
|
|
89
|
+
<tr class="run-row">
|
|
90
90
|
<td><span class="status {{ 'good' if run.labnotes_completed else 'bad' }}" title="{{ 'complete' if run.labnotes_completed else 'not complete' }}">{{ '✓' if run.labnotes_completed else '✕' }}</span></td>
|
|
91
91
|
{% for column in e.run_columns %}{% if column == 'id' and nested %}<td class="mono">{{ run.id.partition('/')[2] or run.id }}</td><td></td>{% else %}<td class="{{ 'mono' if loop.first }}{{ 'num' if column == 'duration' }}">{{ run[column] | duration if column == 'duration' else run[column] | value }}</td>{% endif %}{% endfor %}
|
|
92
92
|
</tr>
|
|
93
|
-
<tr class="record-row" hidden>
|
|
94
|
-
<td colspan="{{ width }}">
|
|
95
|
-
<dl class="record">
|
|
96
|
-
{% for key, value in run.items() if key != 'labnotes_completed' %}
|
|
97
|
-
<dt>{{ key }}</dt>
|
|
98
|
-
{% set shown = value | value %}
|
|
99
|
-
<dd>{% if shown | length > 80 %}<pre>{{ shown }}</pre>{% else %}<code>{{ shown }}</code>{% endif %}</dd>
|
|
100
|
-
{% endfor %}
|
|
101
|
-
</dl>
|
|
102
|
-
</td>
|
|
103
|
-
</tr>
|
|
104
93
|
{% endmacro %}
|
|
105
94
|
{% if nested %}
|
|
106
95
|
{% for group in e.run_groups %}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
{% extends "base.html" %}
|
|
2
|
-
{% from "macros.html" import meter, percent %}
|
|
3
2
|
{% block crumbs %}<span class="crumb">{{ folder }}</span>{% endblock %}
|
|
4
3
|
{% block main %}
|
|
5
4
|
<section class="intro">
|
|
@@ -19,9 +18,7 @@
|
|
|
19
18
|
<thead>
|
|
20
19
|
<tr>
|
|
21
20
|
<th scope="col">Experiment</th>
|
|
22
|
-
<th scope="col">Design</th>
|
|
23
21
|
<th scope="col" class="num">Runs</th>
|
|
24
|
-
<th scope="col" class="progress-col">Grid filled</th>
|
|
25
22
|
</tr>
|
|
26
23
|
</thead>
|
|
27
24
|
<tbody>
|
|
@@ -30,23 +27,9 @@
|
|
|
30
27
|
<td>
|
|
31
28
|
<a class="title-link" href="{{ url_for('experiment', name=experiment.name) }}">{{ experiment.display_name }}</a>
|
|
32
29
|
{% if experiment.display_name != experiment.name %}<div class="study">{{ experiment.name }}</div>{% endif %}
|
|
33
|
-
|
|
34
|
-
<td class="design">
|
|
35
|
-
{% for key, values in experiment.varies.items() %}<span class="factor">{{ key }} <b>{{ values | length }}</b>{% if not loop.last or experiment.runs_per_cell %}<span class="times">×</span>{% endif %}</span> {% endfor %}
|
|
36
|
-
{% if experiment.runs_per_cell %}<span class="factor">runs <b>{{ experiment.runs_per_cell }}</b></span>{% endif %}
|
|
30
|
+
{% if experiment.counts_error %}<div class="counts-error" title="{{ experiment.counts_error }}">counts rule doesn't work</div>{% endif %}
|
|
37
31
|
</td>
|
|
38
32
|
<td class="num" data-label="Runs">{{ experiment.runs }}</td>
|
|
39
|
-
<td class="progress-col">
|
|
40
|
-
{% if experiment.counts_error %}
|
|
41
|
-
<span class="counts-error" title="{{ experiment.counts_error }}">counts rule doesn't work</span>
|
|
42
|
-
{% elif experiment.filled is not none and experiment.target %}
|
|
43
|
-
<div class="progress-line">
|
|
44
|
-
{{ meter(experiment.filled, experiment.target) }}
|
|
45
|
-
<span class="num">{{ experiment.filled }}<span class="of">/{{ experiment.target }}</span></span>
|
|
46
|
-
<span class="pct num">{{ percent(experiment.filled, experiment.target) }}</span>
|
|
47
|
-
</div>
|
|
48
|
-
{% else %}<span class="muted">—</span>{% endif %}
|
|
49
|
-
</td>
|
|
50
33
|
</tr>
|
|
51
34
|
{% endfor %}
|
|
52
35
|
</tbody>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from itertools import product
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def _key(value: object) -> object:
|
|
5
|
-
return int(value) if isinstance(value, bool) else value
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def cell_progress(
|
|
9
|
-
varies: dict[str, list[object]], counts: list[dict[str, object]]
|
|
10
|
-
) -> list[dict[str, object]]:
|
|
11
|
-
by_cell = {tuple(_key(row[key]) for key in varies): row for row in counts}
|
|
12
|
-
cells = []
|
|
13
|
-
for values in product(*varies.values()):
|
|
14
|
-
row = by_cell.get(tuple(_key(value) for value in values), {})
|
|
15
|
-
cells.append(
|
|
16
|
-
{
|
|
17
|
-
"values": dict(zip(varies, values)),
|
|
18
|
-
"runs": row.get("runs", 0),
|
|
19
|
-
"completed": row.get("completed", 0),
|
|
20
|
-
}
|
|
21
|
-
)
|
|
22
|
-
return cells
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
from typing import cast
|
|
2
|
-
|
|
3
|
-
from dirsql import DirSQL
|
|
4
|
-
|
|
5
|
-
from labnotes.cell_progress import cell_progress
|
|
6
|
-
from labnotes.count_runs import count_runs
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
async def experiment_progress(
|
|
10
|
-
tables: DirSQL, source: str, summary: dict[str, object]
|
|
11
|
-
) -> dict[str, object]:
|
|
12
|
-
varies = cast(dict[str, list[object]], summary["varies"])
|
|
13
|
-
completed_run = str(summary["completed_run"])
|
|
14
|
-
runs_per_cell = summary["runs_per_cell"]
|
|
15
|
-
[totals] = await count_runs(tables, source, completed_run)
|
|
16
|
-
progress: dict[str, object] = {**totals, "filled": None, "cells": []}
|
|
17
|
-
if runs_per_cell is None:
|
|
18
|
-
return progress
|
|
19
|
-
grouped = await count_runs(tables, source, completed_run, group_by=list(varies))
|
|
20
|
-
cells = cell_progress(varies, grouped)
|
|
21
|
-
progress["cells"] = cells
|
|
22
|
-
if summary["target"] is None:
|
|
23
|
-
return progress
|
|
24
|
-
progress["filled"] = sum(
|
|
25
|
-
min(cast(int, cell["completed"]), cast(int, runs_per_cell)) for cell in cells
|
|
26
|
-
)
|
|
27
|
-
return progress
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{% macro meter(value, total) -%}
|
|
2
|
-
{%- set share = [value / total, 1] | min if total else 0 -%}
|
|
3
|
-
<span class="meter" role="meter" aria-valuemin="0" aria-valuemax="{{ total }}" aria-valuenow="{{ value }}">
|
|
4
|
-
<span class="meter-fill" style="--share: {{ '%.4f' | format(share) }}"></span>
|
|
5
|
-
</span>
|
|
6
|
-
{%- endmacro %}
|
|
7
|
-
|
|
8
|
-
{% macro percent(value, total) -%}
|
|
9
|
-
{{ '%.0f' | format(100 * value / total) if total else '—' }}%
|
|
10
|
-
{%- endmacro %}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|