From fd2e2c2534f7734782adcf7a528650c862ef0414 Mon Sep 17 00:00:00 2001 From: jebus Date: Thu, 27 Nov 2025 10:28:04 +1300 Subject: [PATCH] [Fix] Post Modern UI deploy Bugfixes (#240) Co-authored-by: Tim Lorsbach Reviewed-on: https://git.envipath.com/enviPath/enviPy/pulls/240 --- envipath/settings.py | 2 +- epdb/models.py | 28 ++++-- epdb/views.py | 21 +++-- templates/actions/objects/model.html | 36 ++++---- templates/collections/objects_list.html | 2 +- .../modals/objects/evaluate_model_modal.html | 1 - .../objects/generic_set_aliases_modal.html | 1 + .../modals/objects/set_license_modal.html | 2 +- utilities/ml.py | 87 ++++++++++++++----- 9 files changed, 127 insertions(+), 53 deletions(-) diff --git a/envipath/settings.py b/envipath/settings.py index 81363f92..3cac2c1a 100644 --- a/envipath/settings.py +++ b/envipath/settings.py @@ -366,7 +366,7 @@ LOGIN_EXEMPT_URLS = [ "/cookie-policy", "/about", "/contact", - "/jobs", + "/careers", "/cite", "/legal", ] diff --git a/epdb/models.py b/epdb/models.py index d44783e2..7fefa928 100644 --- a/epdb/models.py +++ b/epdb/models.py @@ -2282,6 +2282,13 @@ class PackageBasedModel(EPModel): return Dataset.load(ds_path) def retrain(self): + # Reset eval fields + self.eval_results = {} + self.eval_packages.clear() + self.model_status = False + self.save() + + # Do actual retrain self.build_dataset() self.build_model() @@ -2319,7 +2326,7 @@ class PackageBasedModel(EPModel): self.save() def evaluate_model(self, multigen: bool, eval_packages: List["Package"] = None, **kwargs): - if self.model_status != self.BUILT_NOT_EVALUATED: + if self.model_status not in [self.BUILT_NOT_EVALUATED, self.FINISHED]: raise ValueError(f"Can't evaluate a model in state {self.model_status}!") if multigen: @@ -2327,9 +2334,12 @@ class PackageBasedModel(EPModel): self.save() if eval_packages is not None: + self.eval_packages.clear() for p in eval_packages: self.eval_packages.add(p) + self.eval_results = {} + self.model_status = self.EVALUATING self.save() @@ -2383,9 +2393,14 @@ class PackageBasedModel(EPModel): recall = {f"{t:.2f}": [] for t in thresholds} # Note: only one root compound supported at this time - root_compounds = [ - [p.default_node_label.smiles for p in p.root_nodes][0] for p in pathways - ] + root_compounds = [] + for pw in pathways: + if pw.root_nodes: + root_compounds.append(pw.root_nodes[0].default_node_label) + else: + logger.info( + f"Skipping MG Eval of Pathway {pw.name} ({pw.uuid}) as it has no root compounds!" + ) # As we need a Model Instance in our setting, get a fresh copy from db, overwrite the serialized mode and # pass it to the setting used in prediction @@ -3192,7 +3207,7 @@ class EnviFormer(PackageBasedModel): return args def evaluate_model(self, multigen: bool, eval_packages: List["Package"] = None, **kwargs): - if self.model_status != self.BUILT_NOT_EVALUATED: + if self.model_status not in [self.BUILT_NOT_EVALUATED, self.FINISHED]: raise ValueError(f"Can't evaluate a model in state {self.model_status}!") if multigen: @@ -3200,9 +3215,12 @@ class EnviFormer(PackageBasedModel): self.save() if eval_packages is not None: + self.eval_packages.clear() for p in eval_packages: self.eval_packages.add(p) + self.eval_results = {} + self.model_status = self.EVALUATING self.save() diff --git a/epdb/views.py b/epdb/views.py index 57ab0a43..accce6f1 100644 --- a/epdb/views.py +++ b/epdb/views.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List import nh3 from django.conf import settings as s from django.contrib.auth import get_user_model +from django.core.exceptions import BadRequest from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, JsonResponse from django.shortcuts import redirect, render from django.urls import reverse @@ -319,7 +320,7 @@ def get_base_context(request, for_user=None) -> Dict[str, Any]: def _anonymous_or_real(request): - if request.user.is_authenticated and not request.user.is_anonymous: + if request.user and (request.user.is_authenticated and not request.user.is_anonymous): return request.user return get_user_model().objects.get(username="anonymous") @@ -1261,8 +1262,12 @@ def package_compounds(request, package_uuid): compound_name = request.POST.get("compound-name") compound_smiles = request.POST.get("compound-smiles") compound_description = request.POST.get("compound-description") - - c = Compound.create(current_package, compound_smiles, compound_name, compound_description) + try: + c = Compound.create( + current_package, compound_smiles, compound_name, compound_description + ) + except ValueError as e: + raise BadRequest(str(e)) return redirect(c.url) @@ -2819,14 +2824,18 @@ def settings(request): context = get_base_context(request) if request.method == "GET": + context = get_base_context(request) + context["title"] = "enviPath - Settings" + context["object_type"] = "setting" - # Even if settings are aready in "meta", for consistency add it on root level - context["settings"] = SettingManager.get_all_settings(current_user) context["breadcrumbs"] = [ {"Home": s.SERVER_URL}, {"Group": s.SERVER_URL + "/setting"}, ] - return + + context["objects"] = SettingManager.get_all_settings(current_user) + + return render(request, "collections/objects_list.html", context) elif request.method == "POST": if s.DEBUG: for k, v in request.POST.items(): diff --git a/templates/actions/objects/model.html b/templates/actions/objects/model.html index 5f58feda..0172b363 100644 --- a/templates/actions/objects/model.html +++ b/templates/actions/objects/model.html @@ -7,22 +7,26 @@ Edit Model -
  • - - Evaluate Model -
  • -
  • - - Retrain Model -
  • + {% if model.model_status == 'BUILT_NOT_EVALUATED' or model.model_status == 'FINISHED' %} +
  • + + Evaluate Model +
  • + {% endif %} + {% if model.model_status == 'BUILT_NOT_EVALUATED' or model.model_status == 'FINISHED' %} +
  • + + Retrain Model +
  • + {% endif %}
  • -