Source code for immuneML.presentation.html.ValidateClusteringHTMLBuilder

import os
import logging
from pathlib import Path
from typing import List

import pandas as pd

from immuneML.environment.EnvironmentSettings import EnvironmentSettings
from immuneML.ml_methods.util.Util import Util as MLUtil
from immuneML.presentation.TemplateParser import TemplateParser
from immuneML.presentation.html.Util import Util
from immuneML.reports.ReportResult import ReportResult
from immuneML.util.PathBuilder import PathBuilder
from immuneML.workflows.instructions.clustering.ValidateClusteringInstruction import ValidateClusteringState


[docs] class ValidateClusteringHTMLBuilder: CSS_PATH = EnvironmentSettings.html_templates_path / "css/custom.css"
[docs] @staticmethod def build(state: ValidateClusteringState) -> Path: base_path = PathBuilder.build(state.result_path / "../HTML_output/") html_map = ValidateClusteringHTMLBuilder.make_html_map(state, base_path) result_file = base_path / f"ValidateClustering_{state.name}.html" TemplateParser.parse( template_path=EnvironmentSettings.html_templates_path / "ValidateClustering.html", template_map=html_map, result_path=result_file ) return result_file
[docs] @staticmethod def make_html_map(state: ValidateClusteringState, base_path: Path) -> dict: html_map = { "css_style": Util.get_css_content(ValidateClusteringHTMLBuilder.CSS_PATH), "name": state.name, "immuneML_version": MLUtil.get_immuneML_version(), "full_specs": Util.get_full_specs_path(base_path), "logfile": Util.get_logfile_path(base_path), "setting_key": state.cl_item.cl_setting.get_key() if state.cl_item and state.cl_item.cl_setting else "N/A", "validation_types": ", ".join(state.validation_type) if state.validation_type else "N/A", "metrics": ", ".join(state.metrics) if state.metrics else "N/A", "show_labels": state.label_config is not None and len(state.label_config.get_labels_by_name()) > 0, "labels": [{"name": label} for label in state.label_config.get_labels_by_name()] if state.label_config else [], 'predictions_table': ValidateClusteringHTMLBuilder._format_predictions_file(state.predictions_path) if state.predictions_path else "N/A", 'predictions_path': os.path.relpath(state.predictions_path, base_path) if state.predictions_path else "N/A", **Util.make_dataset_html_map(state.dataset), **ValidateClusteringHTMLBuilder._make_method_based_html_map(state, base_path), **ValidateClusteringHTMLBuilder._make_result_based_html_map(state, base_path), **ValidateClusteringHTMLBuilder._make_data_reports_html_map(state, base_path) } return html_map
@staticmethod def _make_data_reports_html_map(state: ValidateClusteringState, base_path: Path) -> dict: """Create HTML map entries for data reports.""" return { "data_reports": ValidateClusteringHTMLBuilder._format_reports( state.data_report_results, base_path ) } @staticmethod def _make_method_based_html_map(state: ValidateClusteringState, base_path: Path) -> dict: """Create HTML map entries for method-based validation results.""" html_map = { "show_method_based": False, "method_based_internal_performance": None, "method_based_external_performance": None, "method_based_reports": {"has_reports": False} } if state.method_based_result is not None: html_map["show_method_based"] = True # Internal performance if state.method_based_result.internal_performance: html_map["method_based_internal_performance"] = ( state.method_based_result.internal_performance.get_df().to_html( border=0, justify='left', max_rows=None, index=False ) ) # External performance if state.method_based_result.external_performance: html_map["method_based_external_performance"] = ( state.method_based_result.external_performance.get_df().to_html( border=0, justify='left', max_rows=None, index=False ) ) # Reports html_map["method_based_reports"] = ValidateClusteringHTMLBuilder._format_reports( state.method_based_report_results, base_path ) return html_map @staticmethod def _make_result_based_html_map(state: ValidateClusteringState, base_path: Path) -> dict: """Create HTML map entries for result-based validation results.""" html_map = { "show_result_based": False, "result_based_internal_performance": None, "result_based_external_performance": None, "result_based_reports": {"has_reports": False} } if state.result_based_result is not None: html_map["show_result_based"] = True # Internal performance if state.result_based_result.internal_performance: html_map["result_based_internal_performance"] = ( state.result_based_result.internal_performance.get_df().to_html( border=0, justify='left', max_rows=None, index=False ) ) # External performance if state.result_based_result.external_performance: html_map["result_based_external_performance"] = ( state.result_based_result.external_performance.get_df().to_html( border=0, justify='left', max_rows=None, index=False ) ) # Reports html_map["result_based_reports"] = ValidateClusteringHTMLBuilder._format_reports( state.result_based_report_results, base_path ) return html_map @staticmethod def _format_predictions_file(file_path: Path) -> str: """Format a predictions CSV file as an HTML table.""" try: df = pd.read_csv(file_path) return df.to_html(border=0, classes="prediction-table", max_rows=None, justify='left', index=False) except Exception as e: logging.warning(f"Error loading predictions: {e}") return "Error loading predictions" @staticmethod def _format_reports(reports: List[ReportResult], base_path: Path) -> dict: """Format report results for HTML display.""" if not reports: return {"has_reports": False} formatted_reports = [] for report in reports: if isinstance(report, ReportResult): formatted_report = { "name": report.name, "info": report.info if hasattr(report, "info") else None, "show_info": hasattr(report, "info") and report.info is not None and len(report.info) > 0, "output_figures": [], "output_tables": [], "output_text": [] } # Process figures if hasattr(report, "output_figures") and report.output_figures: formatted_report["output_figures"] = [{ "name": fig.name, "path": os.path.relpath(fig.path, base_path), "is_embed": str(fig.path).endswith(('.html', '.svg')) } for fig in report.output_figures] # Process tables if hasattr(report, "output_tables") and report.output_tables: for table in report.output_tables: try: formatted_report["output_tables"].append({ "name": table.name, "download_link": os.path.relpath(table.path, base_path), "file_name": os.path.basename(table.path) }) except Exception as e: logging.warning(f"Error processing table {table.name}: {e}") # Process text outputs if hasattr(report, "output_text") and report.output_text: formatted_report["output_text"] = [{ "name": text.name, "download_link": os.path.relpath(text.path, base_path), "file_name": os.path.basename(text.path) } for text in report.output_text] formatted_report["show_tables"] = len(formatted_report["output_tables"]) > 0 formatted_report["show_text"] = len(formatted_report["output_text"]) > 0 formatted_reports.append(formatted_report) return { "has_reports": len(formatted_reports) > 0, "reports": formatted_reports }