# HG changeset patch
# User goeckslab
# Date 1757371115 0
# Node ID b0d893d04d4c6292a67c41691e6e1f189e17922b
# Parent 9e912fce264c5fcc762fa665fc24e97438ff2b3b
planemo upload for repository https://github.com/goeckslab/gleam.git commit 1594d503179f28987720594eb49b48a15486f073
diff -r 9e912fce264c -r b0d893d04d4c image_learner_cli.py
--- a/image_learner_cli.py Wed Aug 27 21:02:48 2025 +0000
+++ b/image_learner_cli.py Mon Sep 08 22:38:35 2025 +0000
@@ -69,7 +69,6 @@
]
rows = []
-
for key in display_keys:
val = config.get(key, None)
if key == "threshold":
@@ -136,15 +135,15 @@
val_str = val
else:
val_str = val if val is not None else "N/A"
- if val_str == "N/A" and key not in [
- "task_type"
- ]: # Skip if N/A for non-essential
+ if val_str == "N/A" and key not in ["task_type"]:
continue
rows.append(
f"
"
- f"
"
+ f"
"
f"{key.replace('_', ' ').title()}
"
- f"
"
+ f"
"
f"{val_str}
"
f"
"
)
@@ -153,13 +152,17 @@
types = [str(a.get("type", "")) for a in aug_cfg]
aug_val = ", ".join(types)
rows.append(
- f"
Augmentation
"
- f"
{aug_val}
"
+ f"
Augmentation
"
+ f"
{aug_val}
"
)
if split_info:
rows.append(
- f"
Data Split
"
- f"
{split_info}
"
+ f"
Data Split
"
+ f"
{split_info}
"
)
html = f"""
Model and Training Summary
@@ -946,6 +949,66 @@
test_viz_dir = base_viz_dir / "test"
html = get_html_template()
+
+ # Extra CSS & JS: center Plotly and enable CSV download for predictions table
+ html += """
+
+
+"""
html += f"
{title}
"
metrics_html = ""
@@ -983,31 +1046,38 @@
except Exception as e:
logger.warning(f"Could not load config for HTML report: {e}")
+ # ---------- image rendering with exclusions ----------
def render_img_section(
- title: str, dir_path: Path, output_type: str = None
+ title: str,
+ dir_path: Path,
+ output_type: str = None,
+ exclude_names: Optional[set] = None,
) -> str:
if not dir_path.exists():
return f"
{title}
Directory not found.
"
- # collect every PNG
+
+ exclude_names = exclude_names or set()
+
imgs = list(dir_path.glob("*.png"))
- # --- EXCLUDE Ludwig's base confusion matrix and any top-N confusion_matrix files ---
+
+ default_exclude = {"confusion_matrix.png", "roc_curves.png"}
+
imgs = [
img
for img in imgs
- if not (
- img.name == "confusion_matrix.png"
- or img.name.startswith("confusion_matrix__label_top")
- or img.name == "roc_curves.png"
- )
+ if img.name not in default_exclude
+ and img.name not in exclude_names
+ and not img.name.startswith("confusion_matrix__label_top")
]
+
if not imgs:
return f"
{title}
No plots found.
"
+
if output_type == "binary":
order = [
"roc_curves_from_prediction_statistics.png",
"compare_performance_label.png",
"confusion_matrix_entropy__label_top2.png",
- # ...you can tweak ordering as needed
]
img_names = {img.name: img for img in imgs}
ordered = [img_names[n] for n in order if n in img_names]
@@ -1019,14 +1089,13 @@
"compare_classifiers_multiclass_multimetric__label_top10.png",
"compare_classifiers_multiclass_multimetric__label_worst10.png",
}
+ valid_imgs = [img for img in imgs if img.name not in unwanted]
display_order = [
"roc_curves.png",
"compare_performance_label.png",
"compare_classifiers_performance_from_prob.png",
"confusion_matrix_entropy__label_top10.png",
]
- # filter and order
- valid_imgs = [img for img in imgs if img.name not in unwanted]
img_map = {img.name: img for img in valid_imgs}
ordered = [img_map[n] for n in display_order if n in img_map]
others = sorted(
@@ -1034,27 +1103,36 @@
)
imgs = ordered + others
else:
- # regression: just sort whatever's left
imgs = sorted(imgs)
- # render each remaining PNG
- html = ""
+
+ html_section = ""
for img in imgs:
b64 = encode_image_to_base64(str(img))
img_title = img.stem.replace("_", " ").title()
- html += (
+ html_section += (
f"
+
+
+"""
-def encode_image_to_base64(image_path):
+def encode_image_to_base64(image_path: str) -> str:
"""Convert an image file to a base64 encoded string."""
with open(image_path, "rb") as img_file:
return base64.b64encode(img_file.read()).decode("utf-8")
-def json_to_nested_html_table(json_data, depth=0):
+def json_to_nested_html_table(json_data, depth: int = 0) -> str:
"""
- Convert JSON object to an HTML nested table.
-
- Parameters:
- json_data (dict or list): The JSON data to convert.
- depth (int): Current depth level for indentation.
-
- Returns:
- str: HTML string for the nested table.
+ Convert a JSON-able object to an HTML nested table.
+ Renders dicts as two-column tables (key/value) and lists as index/value rows.
"""
- # Base case: if JSON is a simple key-value pair dictionary
+ # Base case: flat dict (no nested dict/list values)
if isinstance(json_data, dict) and all(
not isinstance(v, (dict, list)) for v in json_data.values()
):
- # Render a flat table
rows = [
f"
{key}
{value}
"
for key, value in json_data.items()
]
return f"
{''.join(rows)}
"
- # Base case: if JSON is a list of simple values
+ # Base case: list of simple values
if isinstance(json_data, list) and all(
not isinstance(v, (dict, list)) for v in json_data
):
@@ -211,36 +307,34 @@
]
return f"
"
+ )
for key, value in json_data.items()
]
return f"
{''.join(rows)}
"
if isinstance(json_data, list):
rows = [
- f"
[{i}]
"
- f"
{json_to_nested_html_table(value, depth + 1)}
"
+ (
+ f"
[{i}]
"
+ f"
{json_to_nested_html_table(value, depth + 1)}
"
+ )
for i, value in enumerate(json_data)
]
return f"
{''.join(rows)}
"
- # Base case: simple value
+ # Primitive
return f"{json_data}"
-def json_to_html_table(json_data):
+def json_to_html_table(json_data) -> str:
"""
- Convert JSON to a vertically oriented HTML table.
-
- Parameters:
- json_data (str or dict): JSON string or dictionary.
-
- Returns:
- str: HTML table representation.
+ Convert JSON (dict or string) into a vertically oriented HTML table.
"""
if isinstance(json_data, str):
json_data = json.loads(json_data)
@@ -248,56 +342,19 @@
def build_tabbed_html(metrics_html: str, train_val_html: str, test_html: str) -> str:
+ """
+ Build a 3-tab interface:
+ - Config and Results Summary
+ - Train/Validation Results
+ - Test Results
+ Includes a persistent "Help" button that toggles the metrics modal.
+ """
return f"""
-
-
Config and Results Summary
Train/Validation Results
Test Results
-
-
+
@@ -311,17 +368,26 @@
"""
def get_metrics_help_modal() -> str:
+ """
+ Returns a ready-to-use modal with a comprehensive metrics guide and
+ the small script that wires the "Help" button to open/close the modal.
+ """
modal_html = (
'