diff --git a/epdb/management/commands/localize_urls.py b/epdb/management/commands/localize_urls.py
index 91afb0a6..cc0a3726 100644
--- a/epdb/management/commands/localize_urls.py
+++ b/epdb/management/commands/localize_urls.py
@@ -1,8 +1,10 @@
from django.apps import apps
from django.core.management.base import BaseCommand
-from django.db.models import F, Value
-from django.db.models.functions import Replace
+from django.db.models import F, Value, TextField, JSONField
+from django.db.models.functions import Replace, Cast
+
+from epdb.models import EnviPathModel
class Command(BaseCommand):
@@ -49,3 +51,14 @@ class Command(BaseCommand):
obj_cls.objects.update(
url=Replace(F("url"), Value(options["old"]), Value(options["new"]))
)
+ if issubclass(obj_cls, EnviPathModel):
+ obj_cls.objects.update(
+ kv=Cast(
+ Replace(
+ Cast(F("kv"), output_field=TextField()),
+ Value(options["old"]),
+ Value(options["new"]),
+ ),
+ output_field=JSONField(),
+ )
+ )
diff --git a/epdb/views.py b/epdb/views.py
index dd13d21d..4844d3be 100644
--- a/epdb/views.py
+++ b/epdb/views.py
@@ -1454,12 +1454,20 @@ def package_rule(request, package_uuid, rule_uuid):
logger.info(
f"Rule {current_rule.uuid} returned multiple product sets on {smiles}, picking the first one."
)
-
- smirks = f"{stand_smiles}>>{'.'.join(sorted(res[0]))}"
+ # Some Rules are touching unrelated areas which might result in ~ indicating
+ # any bond (-, =, #). For drawing we need a concrete bond. -> use single bond
+ product_smiles = [x.replace("~", "-") for x in res[0]]
+ smirks = f"{stand_smiles}>>{'.'.join(sorted(product_smiles))}"
# Usually the functional groups are a mapping of fg -> count
# As we are doing it on the fly here fake a high count to ensure that its properly highlighted
- educt_functional_groups = {x: 1000 for x in current_rule.reactants_smarts}
- product_functional_groups = {x: 1000 for x in current_rule.products_smarts}
+
+ if isinstance(current_rule, SimpleAmbitRule):
+ educt_functional_groups = {current_rule.reactants_smarts: 1000}
+ product_functional_groups = {current_rule.products_smarts: 1000}
+ else:
+ educt_functional_groups = {x: 1000 for x in current_rule.reactants_smarts}
+ product_functional_groups = {x: 1000 for x in current_rule.products_smarts}
+
return HttpResponse(
IndigoUtils.smirks_to_svg(
smirks,
@@ -1993,9 +2001,42 @@ def package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
if request.method == "GET":
is_image_request = request.GET.get("image")
+ is_highlight_request = request.GET.get("highlight", False)
+ is_highlight_reactivity = request.GET.get("highlightReactivity", False)
if is_image_request:
if is_image_request == "svg":
- svg_data = current_node.as_svg
+ # TODO optimize this chain
+ if is_highlight_request:
+ # User functional groups covered by the model training data
+ fgs = {}
+ if current_pathway.setting:
+ if current_pathway.setting.model:
+ if current_pathway.setting.model.app_domain:
+ fgs = current_pathway.setting.model.app_domain.functional_groups
+
+ svg_data = IndigoUtils.mol_to_svg(
+ current_node.default_node_label.smiles, functional_groups=fgs
+ )
+ elif is_highlight_reactivity:
+ # Use reactant smarts to show all reaction sites
+ # set a high count to obtain a strong color
+ ad_data = current_node.get_app_domain_assessment_data()
+ fgs = {}
+ for t in ad_data.get("assessment", {}).get("transformations", []):
+ r = Rule.objects.get(url=t["rule"]["url"])
+
+ if isinstance(r, SimpleAmbitRule):
+ fgs[r.reactants_smarts] = 1000
+ else:
+ for sr in r.srs:
+ fgs[sr.reactants_smarts] = 1000
+
+ svg_data = IndigoUtils.mol_to_svg(
+ current_node.default_node_label.smiles, functional_groups=fgs
+ )
+ else:
+ svg_data = current_node.as_svg
+
return HttpResponse(svg_data, content_type="image/svg+xml")
context = get_base_context(request)
diff --git a/static/js/pps.js b/static/js/pps.js
index abc92695..c0829ad1 100644
--- a/static/js/pps.js
+++ b/static/js/pps.js
@@ -646,8 +646,8 @@ function handleAssessmentResponse(depict_url, data) {
var reactivityCentersImgSrc = null;
if (data['assessment']['node'] !== undefined) {
- functionalGroupsImgSrc = "
";
- reactivityCentersImgSrc = "
"
+ functionalGroupsImgSrc = "
";
+ reactivityCentersImgSrc = "
"
} else {
functionalGroupsImgSrc = "
";
reactivityCentersImgSrc = "
"
@@ -784,4 +784,4 @@ function handleAssessmentResponse(depict_url, data) {
$("#appDomainAssessmentResultTable").append(res);
-}
\ No newline at end of file
+}
diff --git a/utilities/chem.py b/utilities/chem.py
index 6de46147..279de26f 100644
--- a/utilities/chem.py
+++ b/utilities/chem.py
@@ -729,6 +729,7 @@ class IndigoUtils(object):
height: int = 0,
educt_functional_groups: Dict[str, int] = None,
product_functional_groups: Dict[str, int] = None,
+ debug: bool = False,
):
if educt_functional_groups is None:
educt_functional_groups = {}
@@ -739,6 +740,11 @@ class IndigoUtils(object):
i = Indigo()
renderer = IndigoRenderer(i)
+ if debug:
+ i.setOption("render-atom-ids-visible", True)
+ i.setOption("render-bond-ids-visible", False)
+ i.setOption("render-atom-bond-ids-from-one", True)
+
i.setOption("render-output-format", "svg")
i.setOption("render-coloring", True)
i.setOption("render-image-size", width, height)